题目描述
神犇 YY 虐完数论后给傻× kAc 出了一题
给定 (N, M),求 (1 leq x leq N),(1 leq y leq M) 且 (gcd(x, y)) 为质数的 ((x, y)) 有多少对。
输入格式
第一行一个整数 (T) 表述数据组数。
接下来 (T) 行,每行两个正整数,(N, M)。
输出格式
(T) 行,每行一个整数表示第 (i) 组数据的结果。
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e7+10,M=5e4;
#define ll long long
inline int read(){
int x=0; char c=getchar();
while(c<'0'|c>'9')c=getchar();
while('0'<=c&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); }
return x;
}
ll mu[N],pri[N],f[N],tot;
bool vis[N];
inline void mubius(int n){
mu[1]=vis[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){ pri[++tot]=i; mu[i]=-1; }
for(int j=1;j<=tot&&pri[j]*i<=n;j++){
vis[i*pri[j]]=1;
if(i%pri[j])mu[i*pri[j]]=-mu[i];
else { mu[i*pri[j]]=0; break; }
}
}
for(int i=1;i<=tot;i++)
for(int j=1;pri[i]*j<=n;j++)
f[j*pri[i]]+=mu[j];
for(int i=1;i<=n;i++)f[i]+=f[i-1];
}
signed main(){
int T=read(),n,m;
mubius(1e7);
while(T--){
n=read(),m=read();
ll ans=0;
int lim=min(n,m);
for(int i=1,j=0;i<=lim;i=j+1){
j=min(n/(n/i),m/(m/i));
ans+=(f[j]-f[i-1])*(n/i)*(m/i);
}
printf("%lld
",ans);
}
}