洛谷 P2568 GCD(莫比乌斯反演)
题意:$\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(i,j)\epsilon prime]$。
对于这类题一般就是枚举gcd,可得:
=$\sum_{d\epsilon prime}\sum_{i=1}^{n}\sum_{j=1}^{n}[gcd(i,j)==d]$
=$\sum_{d\epsilon prime}\sum_{i=1}^{{\lfloor \frac{n}{d}\rfloor}}\mu(i){\lfloor \frac{n}{id}\rfloor}{\lfloor \frac{n}{id}\rfloor}$
预处理素数,莫比乌斯前缀和,后面部分整除分块。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=1e7+5; bool p[N]; int pri[N],mu[N],tot; void init() { mu[1]=1; for(int i=2;i<N;i++) { if(!p[i]) pri[tot++]=i,mu[i]=-1; for(int j=0;j<tot&&i*pri[j]<N;j++) { p[i*pri[j]]=true; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; } else mu[i*pri[j]]=-mu[i]; } } for(int i=1;i<N;i++) mu[i]+=mu[i-1]; } ll cal(int n) { ll ans=0; for(int l=1,r;l<=n;l=r+1) { r=n/(n/l); ans+=1LL*(mu[r]-mu[l-1])*(n/l)*(n/l); } return ans; } int main() { init(); int n; scanf("%d",&n); ll ans=0; for(int i=0;i<tot&&pri[i]<=n;i++) { ans+=cal(n/pri[i]); } printf("%lld\n",ans); return 0; }