51nod 1239 欧拉筛模板

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=1000000007,maxn=3000000,p=2333333,N=5000000;
const ll ni=500000004;
int last[p],pre[p],cnt,phi[N+5],pp[N+5];
ll t[p],v[p],n;
bool vis[N+5];
void add(int x,ll y,ll z){++cnt;pre[cnt]=last[x];last[x]=cnt;t[cnt]=y;v[cnt]=z;}
ll calc(ll x){
    if(x<=N)return phi[x];
    int k=x%p;
    ll res=0,l,r,z=x%mod;
    for(int i=last[k];i;i=pre[i])if(t[i]==x)return v[i];
    for(l=2;l<=x;l=r+1){
        r=x/(x/l);res=(res+(r-l+1)%mod*calc(x/l)%mod)%mod;
    }
    res=(z*(z+1)%mod*ni%mod-res+mod)%mod;
    add(k,x,res);
    return res;
}
void euler(){
    for(int i=2;i<=N;++i){
        if(!vis[i])pp[++pp[0]]=i,phi[i]=i-1;
        for(int j=1;j<=pp[0]&&i*pp[j]<=N;++j){
            vis[i*pp[j]]=1;
            if(i%pp[j]==0){phi[i*pp[j]]=phi[i]*pp[j];break;}
            phi[i*pp[j]]=phi[i]*(pp[j]-1);
        }
    }
    phi[1]=1;
    for(int i=1;i<=N;++i)phi[i]=(phi[i]+phi[i-1])%mod;
}
int main(){
    euler();
    cin>>n;
    cout<<calc(n)<<endl;
    //system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/dibaotianxing/p/8205731.html