洛谷P3327:[SDOI2015]约数个数和(莫比乌斯反演)
枚舉倍數的一種靈活的變形:g(d)=∑d∣inf(i)=∑i=1?nd?f(i?d)g(d)=\sum_{d|i}^nf(i)=\sum_{i=1}^{\lfloor\frac{n}ze8trgl8bvbq\rfloor}f(i\cdot d)g(d)=∑d∣in?f(i)=∑i=1?dn???f(i?d)
很顯然,但有時能發揮大作用。
其實本質還是要理解西格瑪究竟是在算什么
解析
一個重要的前置結論:
d(i?j)=∑x∣i,y∣j[gcd?(x,y)=1]d(i\cdot j)=\sum_{x|i,y|j}[\gcd(x,y)=1]d(i?j)=x∣i,y∣j∑?[gcd(x,y)=1]
證明:
嘗試把所有互質的數對 (x,y)(x,y)(x,y) 和 i?ji\cdot ji?j 的所有因子建立雙射關系。首先,對于只有 i,ji,ji,j 一方有的質因子,直接歸給有該項質因子的那一方對應的 xxx 或 yyy。對于雙方都有的質因子 ppp,若 iii 的對應次數為 aaa,jjj 的對應次數為 bbb,如果 i?ji\cdot ji?j 的某個因子 ppp 的次數 ccc 滿足 c≤ac\le ac≤a,就當成 xxx 含有 pcp^cpc 的因子;若 c>ac>ac>a,就當成 yyy 含有 pc?ap^{c-a}pc?a 次方的因子。這樣我們就建立起了雙射關系,且所有的 x,yx,yx,y 都是互質的,證畢。
我們再化一下這個 ddd 函數:
d(i,j)=∑x∣i∑y∣j[gcd?(i,j)=1]=∑x∣i∑y∣j∑k∣gcd?(x,y)μ(k)=∑k∣i,k∣jμ(k)∑k∣x,x∣i∑k∣y,y∣j1=∑k∣i,k∣jμ(k)∑x∣ikik∑y∣jkjk1=∑k∣i,k∣jμ(k)d(ik)d(jk)d(i,j)=\sum_{x|i}\sum_{y|j}[\gcd(i,j)=1]\\=\sum_{x|i}\sum_{y|j}\sum_{k|\gcd(x,y)}\mu(k)\\=\sum_{k|i,k|j}\mu(k)\sum_{k|x,x|i}\sum_{k|y,y|j}1\\=\sum_{k|i,k|j}\mu(k)\sum_{x|\frac{i}{k}}^{\frac{i}{k}}\sum_{y|\frac{j}{k}}^{\frac{j}{k}}1\\=\sum_{k|i,k|j}\mu(k)d(\frac{i}{k})d(\frac{j}{k})d(i,j)=x∣i∑?y∣j∑?[gcd(i,j)=1]=x∣i∑?y∣j∑?k∣gcd(x,y)∑?μ(k)=k∣i,k∣j∑?μ(k)k∣x,x∣i∑?k∣y,y∣j∑?1=k∣i,k∣j∑?μ(k)x∣ki?∑ki??y∣kj?∑kj??1=k∣i,k∣j∑?μ(k)d(ki?)d(kj?)
帶回原式:
∑i=1n∑j=1md(ij)=∑i=1n∑j=1m∑k∣i,k∣jμ(k)d(ik)d(jk)=∑kμ(k)∑k∣in∑k∣jmd(ik)d(jk)=∑kμ(k)∑i=1?nk?∑j=1?mk?d(i)d(j)=∑kμ(k)(∑i=1?nk?d(i))?(∑j=1?mk?d(j))\sum_{i=1}^n\sum_{j=1}^md(ij)=\sum_{i=1}^n\sum_{j=1}^m\sum_{k|i,k|j}\mu(k)d(\frac{i}{k})d(\frac{j}{k})\\=\sum_{k}\mu(k)\sum_{k|i}^n\sum_{k|j}^md(\frac i k)d(\frac j k)\\=\sum_k\mu(k)\sum_{i=1}^{\lfloor\frac n k\rfloor}\sum_{j=1}^{\lfloor\frac m k\rfloor}d(i)d(j)\\=\sum_k\mu(k)(\sum_{i=1}^{\lfloor\frac n k\rfloor}d(i))\cdot(\sum_{j=1}^{\lfloor\frac m k\rfloor}d(j))i=1∑n?j=1∑m?d(ij)=i=1∑n?j=1∑m?k∣i,k∣j∑?μ(k)d(ki?)d(kj?)=k∑?μ(k)k∣i∑n?k∣j∑m?d(ki?)d(kj?)=k∑?μ(k)i=1∑?kn???j=1∑?km???d(i)d(j)=k∑?μ(k)(i=1∑?kn???d(i))?(j=1∑?km???d(j))
線性篩出 μ,d\mu,dμ,d,預處理出前綴和,整除分塊即可。
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=1e5+100; int n,m;int p[N],tot,vis[N],mu[N],msum[N],d[N]; ll dsum[N]; void init(int n){mu[1]=1;d[1]=1;for(int i=2;i<=n;i++){if(!vis[i]) p[++tot]=i,mu[i]=-1,d[i]=2;for(int j=1;j<=tot&&p[j]<=n/i;j++){vis[i*p[j]]=1;if(i%p[j]==0){mu[i*p[j]]=0;d[i*p[j]]=d[i]+d[i]-d[i/p[j]];break;}mu[i*p[j]]=-mu[i];d[i*p[j]]=d[i]*2;}}for(int i=1;i<=n;i++){msum[i]=msum[i-1]+mu[i];dsum[i]=dsum[i-1]+d[i];}return; }signed main() { #ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout); #endifinit(5e4);int T=read();while(T--){n=read();m=read();ll ans(0);for(int l=1,r;l<=min(n,m);l=r+1){r=min(n/(n/l),m/(m/l));ans+=(msum[r]-msum[l-1])*dsum[n/l]*dsum[m/l];}printf("%lld\n",ans);}return 0; } /* 5 5 8 1 46 3564 */總結
以上是生活随笔為你收集整理的洛谷P3327:[SDOI2015]约数个数和(莫比乌斯反演)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一键远程访问公司电脑如何在家远程公司电脑
- 下一篇: 如何在电脑上打出韩国字如何用电脑输入韩语