傳送門c++
A - Lucky 7ide
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { int n; scanf("%d",&n); bool f=false; while(n) { if(n%10==7) f=true; n/=10; } printf("%s\n",f?"Yes":"No"); return 0; }
B - FizzBuzz Sum函數
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { int n; scanf("%d",&n); ll ans=0; for(int i=1;i<=n;i++) { if(i%3==0||i%5==0) continue; ans+=i; } printf("%lld\n",ans); return 0; }
C - Sum of gcd of Tuples (Easy)ui
題意:$\sum_{a=1}^{K} \sum_{b=1}^{K} \sum_{c=1}^{K} gcd(a,b,c)$spa
數據範圍:$1 \leq K \leq 200$code
題解:K比較小,暴力便可。blog
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { int n; scanf("%d",&n); ll ans=0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { for(int k=1;k<=n;k++) { ans+=__gcd(__gcd(i,j),k); } } } printf("%lld\n",ans); return 0; }
D - RGB Tripletsip
題意:給一個長度爲N的字符串S,只包含'R','B','G'。求有多少個三元組$(i,j,k)(1 \leq i <j<k \leq N)$知足$S_{i} \neq S_{j},S_{i} \neq S_{k},S_{j} \neq S_{k}, j-i \neq k-j$。字符串
數據範圍:$1\leq N \leq 4000$get
題解:先將知足$S_{i} \neq S_{j},S_{i} \neq S_{k},S_{j} \neq S_{k}$的算出來,在減去$j-i =k-j$的數目。
總的顯然等於num(R)*num(B)*num(G),而後枚舉兩個端點,判斷第三個端點是否是不一樣於這個兩個端點的顏色。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=4e3+5; char s[N]; int main() { int n; scanf("%d%s",&n,s); int a=0,b=0,c=0; for(int i=0;i<n;i++) { if(s[i]=='R') a++; if(s[i]=='G') b++; if(s[i]=='B') c++; } ll ans=1LL*a*b*c; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(s[i]==s[j]) continue; if(2*j-i<n&&s[i]!=s[2*j-i]&&s[j]!=s[2*j-i]) ans--; } } printf("%lld\n",ans); return 0; }
E - Sum of gcd of Tuples (Hard)
題意:$\sum_{a_{1}=1}^{K} \sum_{a_{2}=1}^{K}...\sum_{a_{N}=1}^{K} gcd(a_{1},a_{2},...,a_{N})$(mod 1e9+7)
數據範圍:$2 \leq N \leq 10^{5},1 \leq K \leq 10^{5}$
題解:
作法0.比賽中寫的莫比烏斯反演,化簡過程:
$Ans=\sum_{a_{1}=1}^{K} \sum_{a_{2}=1}^{K}...\sum_{a_{N}=1}^{K} gcd(a_{1},a_{2},...,a_{N})$
$=\sum_{i=1}^{K}\sum_{a_{1}=1}^{K} \sum_{a_{2}=1}^{K}...\sum_{a_{N}=1}^{K} i[gcd(a_{1},a_{2},...,a_{N})==i]$
$=\sum_{i=1}^{K}\sum_{a_{1}=1}^{\lfloor \frac{K}{i}\rfloor} \sum_{a_{2}=1}^{\lfloor \frac{K}{i}\rfloor}...\sum_{a_{N}=1}^{\lfloor \frac{K}{i}\rfloor} i[gcd(a_{1},a_{2},...,a_{N})==1]$
$=\sum_{i=1}^{K}\sum_{a_{1}=1}^{\lfloor \frac{K}{i}\rfloor} \sum_{a_{2}=1}^{\lfloor \frac{K}{i}\rfloor}...\sum_{a_{N}=1}^{\lfloor \frac{K}{i}\rfloor} i \sum_{d=1}^{\lfloor \frac{K}{i}\rfloor} \mu(d) \lfloor \frac{d}{a_{1}}\rfloor \lfloor \frac{d}{a_{2}}\rfloor ... \lfloor \frac{d}{a_{N}}\rfloor$
$=\sum_{i=1}^{K} i \sum_{d=1}^{\lfloor \frac{K}{i}\rfloor} \mu(d) \sum_{a_{1}=1}^{\lfloor \frac{K}{id}\rfloor} \sum_{a_{2}=1}^{\lfloor \frac{K}{id}\rfloor}...\sum_{a_{N}=1}^{\lfloor \frac{K}{id}\rfloor} 1$
$=\sum_{i=1}^{K} i \sum_{d=1}^{\lfloor \frac{K}{i}\rfloor} \mu(d) \lfloor \frac{K}{id}\rfloor^{N}$
$=\sum_{T=1}^{K} \lfloor \frac{K}{T}\rfloor^{N} \sum_{d|T} \mu(d) \ast {\lfloor \frac{T}{d}\rfloor} (T=id)$
$=\sum_{T=1}^{K} \lfloor \frac{K}{T}\rfloor^{N} \phi(T)$
因爲K不大,預處理歐拉函數,直接遍歷便可。K大的話,整除分塊加杜教篩(霧。
作法1.看了下官方題解:定義f[i]表明gcd爲i的個數,遞推關係式:$f[i]={\lfloor \frac{K}{i}\rfloor}^{N}-\sum_{j>i,i|j}f[j]$。
雙重循環便可,裏面那層循環的複雜度總和是個調和級數,log級別的。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+5; const int MD=1e9+7; int pri[N],tot,phi[N]; bool p[N]; void init() { p[1]=true,phi[1]=1; for(int i=2;i<N;i++) { if(!p[i]) pri[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&i*pri[j]<N;j++) { p[i*pri[j]]=true; if(i%pri[j]==0) { phi[i*pri[j]]=phi[i]*pri[j]; break; } else phi[i*pri[j]]=phi[i]*(pri[j]-1); } } } int quick_pow(int x,int y) { int ans=1; while(y) { if(y&1) ans=1LL*ans*x%MD; y>>=1; x=1LL*x*x%MD; } return ans; } void add(int &x,int y) { x+=y; if(x>=MD) x-=MD; } int main() { init(); int n,k,ans=0; scanf("%d%d",&n,&k); for(int i=1;i<=k;i++) { add(ans,1LL*quick_pow(k/i,n)*phi[i]%MD); } printf("%d\n",ans); return 0; }
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+5; const int MD=1e9+7; int f[N]; int quick_pow(int x,int y) { int ans=1; while(y) { if(y&1) ans=1LL*ans*x%MD; y>>=1; x=1LL*x*x%MD; } return ans; } void add(int &x,int y) { x+=y; if(x>=MD) x-=MD; if(x<0) x+=MD; } int main() { int n,k; scanf("%d%d",&n,&k); for(int i=k;i>=1;i--) { f[i]=quick_pow(k/i,n); for(int j=2*i;j<=k;j+=i) { add(f[i],-f[j]); } } int ans=0; for(int i=1;i<=k;i++) { add(ans,1LL*f[i]*i%MD); } printf("%d\n",ans); return 0; }
F - Select Half
題意:給一個長度爲N的序列A,要求選$\lfloor \frac{N}{2}\rfloor$個數,且下標互不相鄰,最大化它們的總和。
數據範圍:$2 \leq N \leq 2 \times 10^{5}$
題解:對於選的數的下標,$B_{1},B_{2}....,B_{\lfloor \frac{N}{2}\rfloor}$,能夠發現$\sum _{i=2}^{\lfloor \frac{N}{2}\rfloor}B_{i}-B_{i-1}-2 \leq 2$。
所以定義f[i][j]表明選第1~i裏面的數(必選第個i數),前面多空了j的最大值。
$\left\{
\begin{array}{**lr**}
f[i][0]=f[i-2][0]+a[i]\\
f[i][1]=max(f[i-2][1],f[i-3][0])+a[i]\\
f[i][2]=max(f[i-2][2],f[i-3][1],f[i-4][0])+a[i]
\end{array}
\right. $
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=2e5+5; int a[N]; ll f[N][3]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { for(int j=0;j<3;j++) { f[i][j]=-1e18; } } for(int i=1;i<=3;i++) { f[i][i-1]=a[i]; } f[3][0]=a[1]+a[3]; for(int i=4;i<=n;i++) { f[i][0]=f[i-2][0]+a[i]; f[i][1]=max(f[i-2][1],f[i-3][0])+a[i]; f[i][2]=max(f[i-2][2],f[i-3][1])+a[i]; if(i>4) f[i][2]=max(f[i][2],f[i-4][0]+a[i]); } ll ans; if(n&1) ans=max(f[n][2],max(f[n-1][1],f[n-2][0])); else ans=max(f[n][1],f[n-1][0]); printf("%lld\n",ans); return 0; }