原题
求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
借鉴自黄学长博客:
(sum_{isprime(p)}sum^{n}_{x=1}sum^{m}_{y=1}[gcd(x,y)==p])
(=sum_{isprime(p)}sum^{lfloor frac{n}{p}
floor}_{x=1}sum^{lfloor frac{m}{p}
floor}_{y=1}[gcd(x,y)==1])
(=sum_{isprime(p)}sum^{lfloor frac{n}{p}
floor}_{x=1}sum^{lfloor frac{m}{p}
floor}_{y=1}sum_{d|gcd(x,y)}mu(d))
(sum_{isprime(p)}sum^{n/p}_{d=1}mu(d)*lfloor frac{n}{p*d}
floor*lfloor frac{n}{p*d}
floor)
设pd为k
(sum^n_{k=1}sum_{isprime(p) oplus p|k}mu(k/p)*lfloor frac{n}{k}
floor*lfloor frac{n}{k}
floor)
(sum^n_{k=1}F(k)lfloor frac{n}{k}
floor*lfloor frac{n}{k}
floor)
#include<cstdio>
#include<algorithm>
#define N 10000000
typedef long long ll;
using namespace std;
int t,n,m,miu[N+10],prime[N+10],tot;
bool notprime[N+10];
ll ans,sum[N+10];
int read()
{
int ans=0,fu=1;
char j=getchar();
for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
}
void init()
{
miu[1]=1;
for (int i=2;i<=N;i++)
{
if (!notprime[i]) miu[i]=-1,prime[++tot]=i;
for (int j=1;j<=tot && i*prime[j]<=N;j++)
{
notprime[i*prime[j]]=1;
if (i%prime[j]) miu[i*prime[j]]=-miu[i];
else
{
miu[i*prime[j]]=0;
break;
}
}
}
for (int i=1;i<=tot;i++)
for (int j=prime[i];j<=N;j+=prime[i])
sum[j]+=miu[j/prime[i]];
for (int i=2;i<=N;i++)
sum[i]+=sum[i-1];
}
int main()
{
init();
t=read();
while (t--)
{
n=read();
m=read();
ans=0;
if (n>m) swap(n,m);
for (int i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans+=(ll)(n/i)*(m/i)*(sum[last]-sum[i-1]);
}
printf("%lld
",ans);
}
return 0;
}