最大公约数为素数的数对
题目大意
其实就是给你 \(n\),让你求这个式子:
\[\sum\limits_{d\in prime,d\le n}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(i,j)==d]
\]
一看就是莫比乌斯反演,开始反演:
\(\sum\limits_{d\in prime,d\le n}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(i,j)==d]\)
\(=\sum\limits_{d\in prime,d\le n}\sum\limits_{i=1}^{\lfloor\frac{n}{i}\rfloor}\mu(i)\times\lfloor\frac{n}{i\times d}\rfloor^2\)
设 \(T=i\times d\)
\(=\sum\limits_{d\in prime,d\le n}\sum\limits_{i=1}^{\lfloor\frac{n}{i}\rfloor}\mu(i)\times\lfloor\frac{n}{i\times d}\rfloor^2\)
\(=\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2\times\sum\limits_{d|T,d\in prime}\mu(\frac{T}{d})\)
设 \(f_i=\sum\limits_{d|i,d\in prime}\mu(\frac{i}{d})\)
则答案就是
\(=\sum\limits_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2\times f_T\)
直接数论分块+前缀和就行了(虽然数论分块没什么软用)
关键就是求 \(f_i\) 了。
首先,肯定是在求 \(\mu(i)\) 的时候顺便用欧拉筛求一下的。
- \(i\) 为素数,\(\mu(i)=-1,f_i=1\)
- \(i\bmod prime_j\ne0\),那么\(f_{i\times prime_j}=-f_i+\mu(i)\)
- \(i\bmod prime_j=0\),那么\(f_{}i\times prime_j=\mu(i)\)
然后代码就显而易见了。
代码
#include<cstdio>
#define maxn 10000001
#define ll long long
using namespace std;
int n;
int prime[maxn],vis[maxn],u[maxn],f[maxn];
void init(){
u[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i])prime[++prime[0]]=i,u[i]=-1,f[i]=1;
for(int j=1;j<=prime[0]&&(ll)prime[j]*i<=n;j++){
vis[prime[j]*i]=1;
if(i%prime[j]==0){
u[i*prime[j]]=0;
f[i*prime[j]]=u[i];
break;
}
u[i*prime[j]]=-u[i];
f[i*prime[j]]=-f[i]+u[i];
}
}
for(int i=1;i<=n;i++)f[i]+=f[i-1];
}
signed main(){
scanf("%d",&n);
init();
ll ans=0;
for(int l=2,r;l<=n;l=r+1){
r=n/(n/l);
ans+=1ll*(f[r]-f[l-1])*(n/l)*(n/l);
}
printf("%lld",ans);
return 0;
}