【51nod1239】 欧拉函数之和

Description

对正整数n,欧拉函数是小于或等于n的数中与n互质的数的数目。此函数以其首名研究者欧拉命名,它又称为Euler’s totient function、φ函数、欧拉商数等。例如:φ(8) = 4(Phi(8) = 4),因为1,3,5,7均和8互质。
S(n) = Phi(1) + Phi(2) + …… Phi(n),给出n,求S(n),例如:n = 5,S(n) = 1 + 1 + 2 + 2 + 4 = 10,定义Phi(1) = 1。由于结果很大,输出Mod 1000000007的结果。

Solution

这道题本来是不会的,问了一下欧拉函数的性质,石化……

n=d|nϕ(d)

然后这道题就好解了。
f(n)=i=1nϕ(i)=i=1nd|iϕ(i)i=1nd|i,d<iϕ(i)
好像一句废话……
f(n)=i=1nd|iϕ(i)i=1nd|i,d<iϕ(i)=n(n+1)2i=1nd|i,d<iϕ(i)
T=idd|i,d<iT>1
f(n)=n(n+1)2T=2nd=1n/Tϕ(nd)=n(n+1)2T=2nf(nd)
最后分块一下,用哈希表判重就好了。但是,这还是不行,我们还要预处理一下前10^6的答案,这样就解决了。
有另外一道题和这很像 51nod 1244 莫比乌斯函数之和

Code

#include
#include
#include
#include
#include
#define ll long long
using namespace std; 
const ll maxn=1e7+5,mo=1e9+7,mo2=5e8+4,maxn1=1e6+5;
int f[maxn],bz[maxn1+5],d[maxn1],p[maxn+5];
ll h[maxn],n,i,t,j,k,l,x,y,z,ans;
int hash(ll x){
    ll t=x%maxn;
    while (h[t]&& h[t]!=x) t=(t+1)%maxn;
    return t;
}
int dg(ll n){
    if (n<=maxn1) return p[n];
    ll t,i=2,x=n%mo,k=x*(x+1)%mo*mo2%mo,l=hash(n);
    if (h[l]) return f[l];
    while (i<=n){
        t=n/(n/i);
        k=k-(t-i+1)*dg(n/i)%mo;i=t+1;
    }
    k=(k%mo+mo)%mo;
    h[l]=n;f[l]=k;return k;
}
int main(){
    //freopen("data.in","r",stdin);
    p[1]=1;
    for (i=2;i<=maxn1;i++){
        if (!bz[i]) d[++d[0]]=i,p[i]=i-1;
        for (j=1;j<=d[0];j++){
            if (i*d[j]>maxn1) break;
            bz[i*d[j]]=1;
            if (i%d[j]==0){
                p[i*d[j]]=p[i]*d[j];break;
            }p[i*d[j]]=p[i]*p[d[j]];
        }
    }
    for (i=1;i<=maxn1;i++)
        p[i]=(p[i]+p[i-1])%mo;
    scanf("%lld",&n);
    ans=dg(n);
    printf("%lld\n",ans);
}

你可能感兴趣的:(51nod,数论,哈希表)