又是结论题。有一个结论如下:
d(mn)=Σ(i|m)Σ(j|n) [gcd(i,j)=1]。
证明:设m=∏pi^ai(∏是连乘),n=∏pi^bi,允许一些ai,bi=0但不全为0。一个质因子一个考虑下来。假设这个等式对于m=∏p(i-1)^a(i-1)和n=∏p(i-1)^b(i-1)都成立,现在到了pi,设原来的d为d1,那么由约数个数公式可知,加上质因数pi后d为d1*(ai+bi+1),换句话说左边乘上了(ai+bi+1)。现在考虑右边。那么原来gcd=1的所有(i,j),都有gcd(i,j)=1,gcd(i*pi,j)=1,..gcd(i*pi^ai,j)=1,gcd(i,j*pi)=1,..gcd(i,j*pi^bi)=1,所以右边也乘了(ai+ni+1)等式仍然成立。证毕。
利用莫比乌斯函数将原式变形为Σ(i=1,m)Σ(j=1,n)Σ(x|i)Σ(y|j)[gcd(x,y)=1]=Σ(i=1,m)Σ(j=1,n)Σ(d|i,d|j) μ(d)[m/i][n/j]=Σμ(d)Σ[m/xd]Σ[n/yd]=Σμ(d)f(m/d)f(n/d),其中f(x)表示Σ(i=1,x)[x/i],可以在1.5阶内算出。
后来翻到另外一个博客里f(x)表示Σ(i=1,x)d(i),实际上可以线性求出。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100005
#define ll long long
using namespace std;
int n,m,cnt,mu[N],c[N]; bool prm[N]; ll f[N];
void pfs(){
int i,j,k; mu[1]=1; memset(prm,1,sizeof(prm));
for (i=2; i<=50000; i++){
if (prm[i]){
c[++cnt]=i; mu[i]=-1;
}
for (j=1; j<=cnt; j++){
if (i*c[j]>50000) break;
prm[i*c[j]]=0;
if (i%c[j]) mu[i*c[j]]=-mu[i]; else{
mu[i*c[j]]=0; break;
}
}
}
for (i=2; i<=50000; i++) mu[i]+=mu[i-1];
for (i=1; i<=50000; i++)
for (j=1; j<=i; j=k+1){
k=i/(i/j); f[i]+=(ll)(k-j+1)*(i/j);
}
}
int main(){
pfs(); int cas; scanf("%d",&cas);
while (cas--){
scanf("%d%d",&m,&n); int i,j; ll ans=0;
for (i=1; i<=m && i<=n; i=j+1){
j=min(m/(m/i),n/(n/i));
ans+=f[m/i]*f[n/i]*(mu[j]-mu[i-1]);
}
printf("%lld\n",ans);
}
return 0;
}