51nod1238 最小公倍数之和 V3

来源:互联网 发布:网络电视江苏卫视直播 编辑:程序博客网 时间:2024/05/16 12:00

题解

  感觉柿子画起来有点费劲,我太蒻了。

ans=i=1nj=1nij(i,j)=d=1n1dd|ind|jnij[(i,j)=1]=d=1ndi=1ndj=1ndij[(i,j)=1]=d=1nd×(2i=1ndi(j=1ij[(i,j)=1]))1)=d=1nd(2i=1ndiiφ(i)+[i=1]21)=d=1ndi=1ndi2φ(i)

  令f(i)=i2φ(i)s(n)=ni=1f(i)
ans=d=1nd×s(nd)

  id2(n)=n2
d|nd2φ(i)id2(nd)=d|nd2φ(i)n2d2=n3

  要画出杜教筛,要试着对卷积求个前缀和
i=1nd|if(d)id2(id)=id=1nd=1nidf(d)id2(id)=t=1nd=1ntf(d)id2(t)=t=1nid2(t)s(nt)

  因为强迫症,我把t都换成i。(和之前的i没有任何关系)
i=1nid2(i)s(ni)=i=1ni3s(n)=i=1ni3i=2nid2(i)s((ni)

  好了

代码

//杜教筛 #include <cstdio>#include <algorithm>#define maxn 4700000#define mod 1000000007llusing namespace std;typedef long long ll;ll f[maxn+10], phi[maxn+10], _2, _6, N;int prime[maxn+10];bool mark[maxn+10];void shai(){    ll i, j;    phi[1]=1;    for(i=2;i<maxn;i++)    {        if(!mark[i])prime[++*prime]=i, phi[i]=i-1;        for(j=1;i*prime[j]<maxn;j++)        {            mark[i*prime[j]]=1;            if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}            phi[i*prime[j]]=phi[i]*phi[prime[j]];        }    }    for(i=1;i<maxn;i++)phi[i]=(phi[i]*i%mod*i%mod+phi[i-1])%mod;}ll sqr(ll x){if(x>mod)x%=mod;return x*x%mod;}ll s1(ll x){if(x>mod)x%=mod;return x*(1+x)%mod*_2%mod;}ll s2(ll x){if(x>mod)x%=mod;return x*(1+x)%mod*(2*x+1)%mod*_6%mod;}ll s3(ll x){if(x>mod)x%mod;return sqr(s1(x));}ll getf(ll x){return x<maxn?phi[x]:f[N/x];}void djs(ll n){    if(n<maxn or getf(n))return;    ll i, last, t=N/n;    f[t]=s3(n);    for(i=2;i<=n;i=last+1)    {        last=n/(n/i);        djs(n/i);        f[t]=(f[t]-(s2(last)-s2(i-1))*getf(n/i)%mod)%mod;    }}int main(){    ll i, last, ans=0;    _2=500000004;    _6=166666668;    scanf("%lld",&N);    shai();    djs(N);    for(i=1;i<=N;i=last+1)    {        last=N/(N/i);        ans=(ans+getf(N/i)*(s1(last)-s1(i-1)))%mod;    }    printf("%lld",(ans+mod)%mod);    return 0;}
0 0
原创粉丝点击