2019 summer training DAY17 (problem2.b) (Du teach sieve)

Face questions


Formula or a good push, obviously should be set g [i] = i, and the summation Euler function is the same reason, i want to cancel out the front

note! Modulo! Otherwise it will burst long long

And a prime start to take n ^ (2/3) is the best

#include<bits/stdc++.h>
#define mod 1000000007
#define LL long long
using namespace std;
LL read()
{
    LL x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
int prime[1000000],notp[6000001],mu[6000001];
LL tot=0;
map<LL,LL>w;
LL ans[6000003];
void init(LL n)
{
    mu[1]=1;
    for(LL i=2;i<=n;++i)
    {
        if(!notp[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(LL j=1;j<=tot&&i*prime[j]<=n;++j)
        {
            notp[i*prime[j]]=1;
            if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
            else mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=n;++i)ans[i]=(ans[i-1]+mu[i]*i%mod)%mod;
}
LL djs(LL x)
{
    if(x<=6000000)return ans[x];
    if(w[x])return w[x]%mod;
    LL res=1;
    for(LL l=2,r;l&&l<=x;l=r+1)
    {
        r=x/(x/l);
        LL g=(((l+r)%mod*(r-l+1)%mod)%mod*500000004%mod)%mod;//g[i]=i首项加末项乘项数除以2 
        res=(res+mod-(g%mod*djs(x/l))%mod)%mod;//取mod一定要注意!不然会爆long long 
    }
    return w[x]=res%mod;
}
int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    LL n=read();
    //ans[n]=∑(n)h[i]-∑(n)*ans[n/i]
    init(6000000);
    printf("%lld\n",djs(n));
} 
View Code

 

Guess you like

Origin www.cnblogs.com/yyys-/p/11273026.html