最大公约数为素数的数对
题目大意
其实就是给你 \(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;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号