51nod1220-约数之和【莫比乌斯反演,杜教筛】
正題
題目鏈接:http://www.51nod.com/Challenge/Problem.html#problemId=1220
題目大意
給出nnn,求∑i=1n∑j=1nσ(i?j)\sum_{i=1}^n\sum_{j=1}^n\sigma(i*j)i=1∑n?j=1∑n?σ(i?j)
其中σ\sigmaσ表示約數(shù)和。
解題思路
首先有結論σ(i?j)=∑x∣i∑y∣j[gcd(x,y)==1]xyj\sigma(i*j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)==1]\frac{x}{y}jσ(i?j)=x∣i∑?y∣j∑?[gcd(x,y)==1]yx?j
大概是枚舉兩個約數(shù)的占比。
∑i=1n∑j=1n∑x∣i∑y∣i[gcd(x,y)==1]xyj\sum_{i=1}^n\sum_{j=1}^n\sum_{x|i}\sum_{y|i}[gcd(x,y)==1]\frac{x}{y}ji=1∑n?j=1∑n?x∣i∑?y∣i∑?[gcd(x,y)==1]yx?j
這里就直接上反演了
∑d=1nμ(d)∑i=1n∑j=1n∑x∣i∑y∣i[d∣gcd(x,y)]xyj\sum_{d=1}^n\mu(d)\sum_{i=1}^n\sum_{j=1}^n\sum_{x|i}\sum_{y|i}[d|gcd(x,y)]\frac{x}{y}jd=1∑n?μ(d)i=1∑n?j=1∑n?x∣i∑?y∣i∑?[d∣gcd(x,y)]yx?j
∑d=1nμ(d)∑x∣d∑y∣dxy∑x∣i∑y∣jj\sum_{d=1}^n\mu(d)\sum_{x|d}\sum_{y|d}\frac{x}{y}\sum_{x|i}\sum_{y|j}jd=1∑n?μ(d)x∣d∑?y∣d∑?yx?x∣i∑?y∣j∑?j
∑d=1nμ(d)∑x∣d∑y∣dxyy(?ny?+1)?ny??nx?2\sum_{d=1}^n\mu(d)\sum_{x|d}\sum_{y|d}\frac{x}{y}y\frac{(\lfloor\frac{n}{y}\rfloor+1)\lfloor\frac{n}{y}\rfloor\lfloor\frac{n}{x}\rfloor}{2}d=1∑n?μ(d)x∣d∑?y∣d∑?yx?y2(?yn??+1)?yn???xn???
∑d=1nμ(d)∑x∣d?nx?x∑y∣d(?ny?+1)?ny?2\sum_{d=1}^n\mu(d)\sum_{x|d}\lfloor\frac{n}{x}\rfloor x\sum_{y|d}\frac{(\lfloor\frac{n}{y}\rfloor+1)\lfloor\frac{n}{y}\rfloor}{2}d=1∑n?μ(d)x∣d∑??xn??xy∣d∑?2(?yn??+1)?yn???
∑d=1nμ(d)d∑x=1?nd??nxd?x∑y=1?nd?(?nyd?+1)?nyd?2\sum_{d=1}^n\mu(d)d\sum_{x=1}^{\lfloor\frac{n}ozvdkddzhkzd\rfloor}\lfloor\frac{n}{xd}\rfloor x\sum_{y=1}^{\lfloor\frac{n}ozvdkddzhkzd\rfloor}\frac{(\lfloor\frac{n}{yd}\rfloor+1)\lfloor\frac{n}{yd}\rfloor}{2}d=1∑n?μ(d)dx=1∑?dn????xdn??xy=1∑?dn???2(?ydn??+1)?ydn???
前面那個∑d=1nμ(d)d\sum_{d=1}^n\mu(d)d∑d=1n?μ(d)d可以杜教篩來求,卷上一個ididid之后∑d∣nμ(d)?d?nd=n∑d∣nμ(d)\sum_{d|n}\mu(d)*d*\frac{n}ozvdkddzhkzd=n\sum_{d|n}\mu(d)∑d∣n?μ(d)?d?dn?=n∑d∣n?μ(d)就是?\epsilon?了。
考慮如何求后面那兩個,第一個我們把它化簡一下∑i=1n(?ni?+1)?ni?2=∑i=1ni?ni?\sum_{i=1}^{n}\frac{(\lfloor\frac{n}{i}\rfloor+1)\lfloor\frac{n}{i}\rfloor}{2}=\sum_{i=1}^{n}i\lfloor\frac{n}{i}\rfloori=1∑n?2(?in??+1)?in???=i=1∑n?i?in??
就和前面那個式子一樣了,對于這個式子,我們可以理解為枚舉每個數(shù)作為約數(shù)的次數(shù),那么就有∑i=1ni?ni?=∑i=1nσ(i)\sum_{i=1}^ni\lfloor\frac{n}{i}\rfloor=\sum_{i=1}^n\sigma(i)i=1∑n?i?in??=i=1∑n?σ(i)
這樣我們就可以線性篩出比較小時的答案,然后比較大的時候就直接整除分塊搞就好了。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<map> #define ll long long using namespace std; const ll N=2e6,P=1e9+7; ll n,cnt,low[N],pre[N],mu[N],pri[N],s[N]; map<ll ,ll > mark;bool v[N]; void Prime(){mu[1]=s[1]=1;for(ll i=2;i<N;i++){if(!v[i])s[i]=i+1,mu[i]=-i,low[i]=i,pri[++cnt]=i;for(ll j=1;j<=cnt&&i*pri[j]<N;j++){v[i*pri[j]]=1;if(i%pri[j]==0){low[i*pri[j]]=low[i]*pri[j];s[i*pri[j]]=(s[i]*pri[j]+s[i/low[i]])%P;break;}low[i*pri[j]]=pri[j];s[i*pri[j]]=s[i]*s[pri[j]]%P;mu[i*pri[j]]=mu[i]*mu[pri[j]];}}for(ll i=1;i<N;i++)mu[i]=(mu[i]+mu[i-1])%P,s[i]=(s[i-1]+s[i])%P;return; } ll Get_Mu(ll n){if(n<N)return mu[n];if(mark[n])return mark[n];ll ans=1;for(ll l=2,r;l<=n;l=r+1){r=n/(n/l);ans=(ans-Get_Mu(n/l)*(r*(r+1)/2-l*(l-1)/2)%P)%P;}return mark[n]=(ans+P)%P; } ll Get_Sum(ll n){if(n<N)return s[n];ll ans=0;for(ll l=1,r;l<=n;l=r+1){r=n/(n/l);ans=(ans+(n/l)*(r*(r+1)/2-l*(l-1)/2)%P)%P;}return (ans+P)%P; } int main() {Prime();scanf("%lld",&n);ll ans=0;for(ll l=1,r;l<=n;l=r+1){r=n/(n/l);ll tmp=Get_Sum(n/l);tmp=tmp*tmp%P;ans=(ans+(Get_Mu(r)-Get_Mu(l-1))*tmp%P)%P;}printf("%lld",(ans+P)%P); }總結
以上是生活随笔為你收集整理的51nod1220-约数之和【莫比乌斯反演,杜教筛】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P3172-[CQOI2015]选数【d
- 下一篇: P3702-[SDOI2017]序列计数