莫比乌斯反演
这道题有一个我不知道的结论:
证明过程:
设 nm=px11⋅px22⋅px33⋯pxkk n m = p 1 x 1 ⋅ p 2 x 2 ⋅ p 3 x 3 ⋯ p k x k 且 n=py11⋅py22⋅py33⋯pykk n = p 1 y 1 ⋅ p 2 y 2 ⋅ p 3 y 3 ⋯ p k y k ,则 m=px1−y11⋅px2−y22⋅px3−y33⋯pxk−ykk m = p 1 x 1 − y 1 ⋅ p 2 x 2 − y 2 ⋅ p 3 x 3 − y 3 ⋯ p k x k − y k 。
设 i=pa11⋅pa22⋅pa33⋯pakk i = p 1 a 1 ⋅ p 2 a 2 ⋅ p 3 a 3 ⋯ p k a k , j=pb11⋅pb22⋅pb33⋯pbkk j = p 1 b 1 ⋅ p 2 b 2 ⋅ p 3 b 3 ⋯ p k b k ,要使 gcd(i,j)=1 gcd ( i , j ) = 1 ,必然有 a1 a 1 或 b1 b 1 为 0,如果 a1 a 1 为 0,那么 b1 b 1 有 xi−y1+1 x i − y 1 + 1 种取值;如果 b1 b 1 为 0,那么 a1 a 1 有 y1+1 y 1 + 1 种取值,一共有 x1+1 x 1 + 1 种取值,对于 xi x i 也如此。
所以满足条件的 i,j i , j 对数为 ∏(xi+1) ∏ ( x i + 1 ) ,与约数定理给出的形式一样,得证。——By sengxian
现在我们来推式子:
因为 d(x) d ( x ) 是积性函数,所以可以线性筛预处理并算出前缀和,然后分块统计。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 50005
#define F inline
using namespace std;
typedef long long LL;
int t,n,m,c,mu[N],p[N],a[N],b[N];
bool f[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
F void mkp(){
mu[1]=a[1]=1,f[1]=true;
for (int i=2;i<N;i++){
if (!f[i]) p[++c]=i,mu[i]=-1,a[i]=2,b[i]=1;
for (int j=1,k;j<=c&&(k=p[j]*i)<N;j++){
f[k]=true;
if (i%p[j]==0){
mu[k]=0,a[k]=a[i]/(b[i]+1)*(b[i]+2);
b[k]=b[i]+1; break;
}
else mu[k]=-mu[i],a[k]=a[i]*2,b[k]=1;
}
}
for (int i=2;i<N;i++) mu[i]+=mu[i-1],a[i]+=a[i-1];
}
int main(){
for (mkp(),t=_read();t;t--){
n=_read(),m=_read(); if (n>m) swap(n,m);
LL ans=0; int p;
for (int i=1;i<=n;i=p+1){
p=min(n/(n/i),m/(m/i));
ans+=1ll*(mu[p]-mu[i-1])*a[n/i]*a[m/i];
}
printf("%lld\n",ans);
}
return 0;
}