参考博客:bzoj3994/洛谷P3327 莫比乌斯反演
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=50000+100;
ll F[maxn]; //F[i] 表示i的约数个数
int num[maxn]; //num[i] 表示i最小素因子的指数
int mu[maxn];
int prime[maxn],tot;
bool isprime[maxn];
void init(){
for(int i=0;i<maxn;i++) isprime[i]=true;
isprime[0]=isprime[1]=false;
tot=0;
F[1]=1;
mu[1]=1;
for(int i=2;i<maxn;i++){
if(isprime[i]) prime[tot++]=i,F[i]=2,num[i]=1,mu[i]=-1;
for(int j=0;j<tot && i*prime[j]<maxn;j++){
isprime[i*prime[j]]=false;
if(i%prime[j]) F[i*prime[j]]=F[i]*2,num[i*prime[j]]=1,mu[i*prime[j]]=-mu[i];
else{
F[i*prime[j]]=F[i]/(num[i]+1)*(num[i]+2);
num[i*prime[j]]=num[i]+1;
break;
}
}
}
for(int i=2;i<maxn;i++) F[i]+=F[i-1],mu[i]+=mu[i-1];
}
int main(){
init();
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
int ind;
ll res=0;
if(n>m) swap(n,m);
for(int i=1;i<=n;i=ind+1){
ind=min(n/(n/i),m/(m/i));
res+=(ll)(mu[ind]-mu[i-1])*F[n/i]*F[m/i];
}
printf("%lld\n",res);
}
}