bzoj3994 约数个数和 数论&莫比乌斯反演

来源:互联网 发布:淘宝考试答题器 编辑:程序博客网 时间:2024/04/30 16:55

       又是结论题。有一个结论如下:

       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 longusing 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;}

1 0
原创粉丝点击