学习莫比乌斯反演最大的感觉就是:这完全靠智商硬核推公式啊。
d(ij)的约数个数预备知识:
我们切换一下枚举次序:(考验智商了)
莫比乌斯函数性质:
代换:
假设n<=m,再次切换枚举次序:(再次考验智商了)
设
我们先从1到50000打表g(x),接下来就可以直接整除分块了解决这个题了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e6+10;
int pri[maxn],vis[maxn],mu[maxn],cnt;
ll g[maxn],sum[maxn];
void get_mu(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])mu[i]=-1,pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i<=n;j++)
{
vis[pri[j]*i]=1;
if(i%pri[j]==0)break;
else mu[pri[j]*i]=-mu[i];
}
}
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+mu[i];
for(int i=1;i<=n;i++)
for(int l=1,r;l<=i;l=r+1)
{
r=i/(i/l);
g[i]+=1ll*(r-l+1)*(i/l);
}
}
int main()
{
int T,n,m;
get_mu(5e4);
scanf("%d",&T);
while(T--)
{
ll ans=0;
scanf("%d%d",&n,&m);
int nn=min(n,m);
for(int l=1,r;l<=nn;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ans+=1ll*(sum[r]-sum[l-1])*g[n/l]*g[m/l];
}
printf("%lld\n",ans);
}
}