题目大意:求有多少数对 ( x , y ) (x,y) (x,y) ( 1 < = x < = n , 1 < = y < = m ) (1<=x<=n,1<=y<=m) (1<=x<=n,1<=y<=m)满足 g c d ( x , y ) gcd(x,y) gcd(x,y)为质数。
此题需要用到莫比乌斯反演。
题意即求
∑ k = 1 n ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = k ] ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^n_{i=1}\sum\limits^m_{j=1}[gcd(i,j)==k]\qquad(k\in prime) k=1∑ni=1∑nj=1∑m[gcd(i,j)==k](k∈prime)
两边同时除以 k k k,将 [ g c d ( i , j ) = = k ] [gcd(i,j)==k] [gcd(i,j)==k]化成 [ g c d ( i , j ) = = 1 ] [gcd(i,j)==1] [gcd(i,j)==1]
∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ [ g c d ( i , j ) = = 1 ] ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{i=1}\sum\limits^{⌊\frac{m}{k}⌋}_{j=1}[gcd(i,j)==1]\qquad(k\in prime) k=1∑ni=1∑⌊kn⌋j=1∑⌊km⌋[gcd(i,j)==1](k∈prime)
我们知道莫比乌斯函数的性质
∑ d ∣ n μ ( d ) = [ n = = 1 ] \sum\limits_{d|n}μ(d)=[n==1] d∣n∑μ(d)=[n==1]
我们把 n n n换成 g c d ( i , j ) gcd(i,j) gcd(i,j),得 [ g c d ( i , j ) = = 1 ] = ∑ d ∣ g c d ( i , j ) μ ( d ) [gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}μ(d) [gcd(i,j)==1]=d∣gcd(i,j)∑μ(d)
原式变为
∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ m k ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{i=1}\sum\limits^{⌊\frac{m}{k}⌋}_{j=1}\sum\limits_{d|gcd(i,j)}μ(d)\qquad(k\in prime) k=1∑ni=1∑⌊kn⌋j=1∑⌊km⌋d∣gcd(i,j)∑μ(d)(k∈prime)
枚举 d d d
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n k d ⌋ ∗ ⌊ m k d ⌋ ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{d=1}μ(d)*⌊\frac{n}{kd}⌋*⌊\frac{m}{kd}⌋\qquad(k\in prime) k=1∑nd=1∑⌊kn⌋μ(d)∗⌊kdn⌋∗⌊kdm⌋(k∈prime)
令 T = k d T=kd T=kd,有
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n T ⌋ ∗ ⌊ m T ⌋ ( k ∈ p r i m e ) \sum\limits^n_{k=1}\sum\limits^{⌊\frac{n}{k}⌋}_{d=1}μ(d)*⌊\frac{n}{T}⌋*⌊\frac{m}{T}⌋\qquad(k\in prime) k=1∑nd=1∑⌊kn⌋μ(d)∗⌊Tn⌋∗⌊Tm⌋(k∈prime)
枚举 T T T,提到前面
∑ T = 1 n ⌊ n T ⌋ ∗ ⌊ m T ⌋ ∑ k ∣ T , k ∈ p r i m e μ ( T k ) \sum\limits^n_{T=1}⌊\frac{n}{T}⌋*⌊\frac{m}{T}⌋\sum\limits_{k|T,k\in prime}μ(\frac{T}{k}) T=1∑n⌊Tn⌋∗⌊Tm⌋k∣T,k∈prime∑μ(kT)
用数论分块处理即可,时间复杂度为 O ( n ln n + T n ) O(n\ln n+T\sqrt n) O(nlnn+Tn)。
code
#include<bits/stdc++.h>
#define N 10000000
using namespace std;
int t,n,m,fl[N+5],p[N+5],mu[N+5],f[N+5];
long long ans,sum[N+5];
void dd(){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!fl[i]){
p[++p[0]]=i;mu[i]=-1;
}
for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
fl[i*p[j]]=1;
if(i%p[j]==0){
mu[i*p[j]]=0;
break;
}
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=p[0];i++){
for(int j=1;p[i]*j<=N;j++){
f[p[i]*j]+=mu[j];
}
}
for(int i=1;i<=N;i++){
sum[i]=sum[i-1]+f[i];
}
}
void ss(){
ans=0;
for(int l=1,r=0;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(sum[r]-sum[l-1])*(n/l)*(m/l);
}
}
int main()
{
dd();
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
ss();
printf("%lld\n",ans);
}
return 0;
}