Description:
求(sum_{i=1}^{n} sum_{j=1}^{m} gcd(i,j)==p _{p in Prime})
Hint:
(数据组数<=1e4,n,m<=1e7)
Solution:
$ sum_{p in Prime} sum_{i=1}^{n} sum_{j=1}^{m} gcd(i,j)==p $
$ sum_{p in Prime} sum_{i=1}^{ lfloor frac {n} {p} floor } sum_{j=1}^{ lfloor frac {m} {p} floor } gcd(i,j)==1 $
$ sum_{p in Prime} sum_{i=1}^{ lfloor frac {n} {p} floor } sum_{j=1}^{ lfloor frac {m} {p} floor } sum_{d|gcd(i,j)} mu(d) $
$ sum_{p in Prime} sum_{i=1}^{ lfloor frac {n} {p} floor } sum_{j=1}^{ lfloor frac {m} {p} floor } sum_{d|gcd(i,j)} mu(d) $
$ sum_{p in Prime} sum_{i=1}^{ lfloor frac {n} {p} floor } sum_{j=1}^{ lfloor frac {m} {p} floor } [ d | i ][ d | j] mu(d) $
$ sum_{p in Prime} sum_{d}^{lfloor frac {min(n,m)} {p} floor} mu (d) sum_{i=1}^{ lfloor frac {n} {p} floor } sum_{j=1}^{ lfloor frac {m} {p} floor } $
$ sum_{p in Prime} sum_{d}^{lfloor frac {min(n,m)} {p} floor} mu (d) lfloor frac {n} {dp} floor lfloor frac {m} {dp} floor $
换元得
$ sum_{p in Prime} sum_{T=1}^{min(n,m)} mu (frac{T}{p}) lfloor frac {n} {T} floor lfloor frac {m} {T} floor $
$ sum_{T=1}^{min(n,m)} lfloor frac {n} {T} floor lfloor frac {m} {T} floor sum_{p in Prime} mu(frac{T}{p}) $
将前缀和特殊处理一下,直接枚举T即可
#include<bits/stdc++.h>
using namespace std;
const int mxn=1e7+5;
int n,m,T,tot,mu[mxn],vis[mxn],p[mxn],f[mxn];
long long sum[mxn];
void sieve(int lim)
{
mu[1]=1;
for(int i=2;i<=lim;++i) {
if(!vis[i]) mu[i]=-1,p[++tot]=i;
for(int j=1;j<=tot;++j) {
if(p[j]*i>lim) break;
vis[p[j]*i]=1;
if(i%p[j]==0) {
mu[i*p[j]]=0;
break;
}
mu[p[j]*i]=-mu[i];
}
}
for(int i=1;i<=lim;++i) {
for(int j=1;j<=tot;++j) {
if(p[j]*i>lim) break;
else f[p[j]*i]+=mu[i]; //特殊处理
}
}
for(int i=1;i<=lim;++i) sum[i]=sum[i-1]+f[i];
}
int main()
{
scanf("%d",&T);
sieve(10000000);
while(T--) {
long long ans=0;
scanf("%d%d",&n,&m); if(n>m) swap(n,m);
for(int l=1,r;l<=n;l=r+1) {
r=min(n/(n/l),m/(m/l));
ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
}
printf("%lld
",ans);
}
return 0;
}