题目链接:YY的GCD
公式和上一题一样地推
最后得到答案为
令T=pd',化简公式得到
后面那个sigma可以线性筛筛出来,枚举素数贡献答案即可
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=100000+10;
const int N=10000000+1;
int n,m,d;
LL sum[N];
int mu[N],p[N/10],f[N];
bool vis[N];
void make_mobius(){
int cnt=0; mu[1]=1;
for (int i=2;i<=N;++i){
if (!vis[i]){
p[++cnt]=i;
mu[i]=-1;
}
for (int j=1;j<=cnt&&i*p[j]<=N;j++){
vis[i*p[j]]=1;
if (i%p[j]==0){
mu[i*p[j]]=0;
break;
}else mu[i*p[j]]=-mu[i];
}
}
for (int i=1;i<=cnt;++i)
for (int j=p[i];j<=N;j+=p[i])
f[j]+=mu[j/p[i]];
for (int i=1;i<=N;++i) sum[i]=sum[i-1]+f[i];
}
void solve(int n,int m){
int pos;
LL ans=0;
for (int i=1;i<=min(n,m);i=pos+1){
pos=min(n/(n/i),m/(m/i));
ans+=(sum[pos]-sum[i-1])*1LL*(n/i)*(m/i);
} printf("%lld\n",ans);
}
int main(){
int t; scanf("%d",&t);
make_mobius();
while (t--){
scanf("%d%d",&n,&m);
solve(n,m);
}
}