题目链接
给定 N , M N, M N,M,求 1 ≤ x ≤ N , 1 ≤ y ≤ M 1 \leq x \leq N,1 \leq y \leq M 1≤x≤N,1≤y≤M 且 gcd ( x , y ) \gcd(x, y) gcd(x,y)为质数的 ( x , y ) (x, y) (x,y) 有多少对。
T T T组样例, T = 1 0 4 , N , M ≤ 1 0 7 T = 10^{4} ,N,M\leq10^{7} T=104,N,M≤107
根据题意写出式子,
∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) 为 质 数 ] \sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)为质数] ∑i=1N∑j=1M[gcd(i,j)为质数]
提出 g c d gcd gcd, 变成
∑ g = 1 m i n ( N , M ) ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] [ g 为 质 数 ] \sum_{g=1}^{min(N,M)}\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g][g为质数] ∑g=1min(N,M)∑i=1N∑j=1M[gcd(i,j)=g][g为质数]
不妨让 N < M N
就变成 ∑ g = 1 N [ g 为 质 数 ] ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] \sum_{g=1}^{N}[g为质数]\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g] ∑g=1N[g为质数]∑i=1N∑j=1M[gcd(i,j)=g]了,写起来舒服点。
令 f ( g ) = ∑ i = 1 N ∑ j = 1 M [ g c d ( i , j ) = g ] f(g)=\sum_{i=1}^{N}\sum_{j=1}^{M}[gcd(i,j)=g] f(g)=∑i=1N∑j=1M[gcd(i,j)=g]
令 F ( g ) = ∑ g ∣ d f ( d ) = ∑ i = 1 N ∑ j = 1 M [ g ∣ g c d ( i , j ) ] = ⌊ N g ⌋ ⌊ M g ⌋ F(g)=\sum_{g|d}f(d)=\sum_{i=1}^{N}\sum_{j=1}^{M}[g|gcd(i,j)]=\lfloor \frac{N}{g}\rfloor \lfloor\frac{M}{g} \rfloor F(g)=∑g∣df(d)=∑i=1N∑j=1M[g∣gcd(i,j)]=⌊gN⌋⌊gM⌋
根据莫比乌斯反演公式有 f ( g ) = ∑ g ∣ d μ ( d g ) F ( d ) f(g)=\sum_{g|d}\mu(\frac{d}{g})F(d) f(g)=∑g∣dμ(gd)F(d)
代回原式子得,
∑ g = 1 N [ g 为 质 数 ] f ( g ) = ∑ g = 1 N [ g 为 质 数 ] ∑ g ∣ d μ ( d g ) ⌊ N d ⌋ ⌊ M d ⌋ \sum_{g=1}^{N}[g为质数]f(g)=\sum_{g=1}^{N}[g为质数]\sum_{g|d}\mu(\frac{d}{g})\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor ∑g=1N[g为质数]f(g)=∑g=1N[g为质数]∑g∣dμ(gd)⌊dN⌋⌊dM⌋
= ∑ d = 1 N ⌊ N d ⌋ ⌊ M d ⌋ ∑ g ∣ d μ ( d g ) [ g 为 质 数 ] =\sum_{d=1}^{N}\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor\sum_{g|d}\mu(\frac{d}{g})[g为质数] =∑d=1N⌊dN⌋⌊dM⌋∑g∣dμ(gd)[g为质数]
= ∑ d = 1 N ⌊ N d ⌋ ⌊ M d ⌋ S ( d ) =\sum_{d=1}^{N}\lfloor \frac{N}{d}\rfloor \lfloor\frac{M}{d} \rfloor S(d) =∑d=1N⌊dN⌋⌊dM⌋S(d)
其中我们令 S ( d ) = ∑ g ∣ d μ ( d g ) [ g 为 质 数 ] S(d)=\sum_{g|d}\mu(\frac{d}{g})[g为质数] S(d)=∑g∣dμ(gd)[g为质数],我们只要预处理出 S ( d ) S(d) S(d), 再处理出 S ( d ) S(d) S(d)的前缀和,就可以用数论分块求答案了。
那么预处理 S ( d ) S(d) S(d),我们可以对于每个数分解质因子计算贡献,也可以对于每个质数,把贡献加到它的所有倍数中,两种做法都可以 o ( n l o g n ) o(nlogn) o(nlogn)。
#include
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
typedef pair<int,int> P;
const int MAXN=10000000;
int prime[MAXN+10],notPrime[MAXN+10],mu[MAXN+10],tot;
void initMu(int n)
{
notPrime[1]=mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!notPrime[i])prime[tot++]=i,mu[i]=-1;
for(int j=0;j<tot&&i*prime[j]<=n;j++)
{
notPrime[i*prime[j]]=1;
if(i%prime[j])mu[i*prime[j]]=-mu[i];
else {mu[i*prime[j]]=0;break;}
}
}
}
int f[MAXN+10];
int main()
{
initMu(MAXN);
for(int i=1;i<=MAXN;i++)if(!notPrime[i])
{
for(int j=i;j<=MAXN;j+=i)
{
f[j]+=mu[j/i];
}
}
for(int i=1;i<=MAXN;i++)f[i]+=f[i-1];
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
if(n>m)swap(n,m);
ll ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ans=ans+1ll*(n/l)*(m/l)*(f[r]-f[l-1]);
}
printf("%lld\n",ans);
}
return 0;
}