最大公约数为素数的数对

题目大意

其实就是给你 \(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;
}
posted @ 2022-06-11 15:21  A_zjzj  阅读(44)  评论(0编辑  收藏  举报