题意:给定\(N,M(N,M<=10^7)\),求\(\sum_{P∈prime}\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==P]\).
分析:按照套路,设
\(f(P)=\sum_{i=1}^N\sum_{j=1}^M[gcd(i,j)==P]\)
\(F(P)=\sum_{P|d}f(d)\)
\(F(P)\)式子是指在1到\(N\)和1到\(M\)中各选出一个数,使得这两个数的\(gcd\)是\(P\)的倍数,故\(F(P)=\lfloor\frac NP\rfloor\lfloor\frac MP\rfloor\)
又由莫比乌斯反演定理得\(f(P)=\sum_{P|x}μ(\frac xP)F(x)\)
故\(f(P)=\sum_{P|x}μ(\frac xP)\lfloor\frac Nx\rfloor\lfloor\frac Mx\rfloor\)
故\(ans=\sum_{P∈prime}f(P)\)
\(=\sum_{P∈prime}\sum_{P|x}μ(\frac xP)\lfloor\frac Nx\rfloor\lfloor\frac Mx\rfloor\)
到了这一步就需要思考一下了,如果按照我们之前的做法,那么继续转化式子得\(ans=\sum_{P∈prime}\sum_{x=1}^{min(\lfloor\frac NP\rfloor,\lfloor\frac MP\rfloor)}μ(\frac xP)\lfloor\frac Nx\rfloor\lfloor\frac Mx\rfloor\),时间复杂度为\(O(N*lnN*\sqrt N)\),亲测超时.
所以我们需要另一种优化方法,\(ans=\sum_{x=1}^{min(N,M)}\lfloor\frac Nx\rfloor\lfloor\frac Mx\rfloor\sum_{P|x,P∈prime}μ(\frac xP)\),时间复杂度\(O(\sqrt N+N*lnN)=O(N*lnN)\)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read(){
   int s=0,w=1;char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
   return s*w;
}
const int N=10000005;
int v[N],sum[N],prime[N],mu[N];
inline void get_mu(){
    mu[1]=1;int m=0;
    for(int i=2;i<N;i++){
		if(!v[i]){
	    	v[i]=i;
	    	prime[++m]=i;
	    	mu[i]=-1;
		}
		for(int j=1;j<=m;j++){
	    	if(i*prime[j]>N)break;
	    	v[i*prime[j]]=prime[j];
	    	if(i%prime[j]==0)break;
	    	mu[i*prime[j]]=-mu[i];
		}
    }
    for(int i=1;i<=m;i++)
		for(int j=1;j*prime[i]<N;j++)
	    	sum[j*prime[i]]+=mu[j];
    for(int i=1;i<N;i++)sum[i]+=sum[i-1];
}
int main(){
    get_mu();
    int T=read();
    while(T--){
		int n=read(),m=read();LL ans=0;
		for(int l=1,r;l<=min(n,m);l=r+1){
	    	r=min(n/(n/l),m/(m/l));
	    	ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
		}
		printf("%lld\n",ans);
    }
    return 0;
}