【51Nod 1239】欧拉函数之和

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

跟莫比乌斯函数之和
f(n)=ni=1φ(i)
所以 ans=f(b)f(a1)
由于与莫比乌斯函数之和类似,脑袋O(1)得解。
d|nφ(d)=n 关于欧拉函数的一个性质
ni=1d|iφ(d)=(n+1)n/2
熟练掌握内层外移的话,这种东西只可以转化的。
这个式子= nd=1ndi=1φ(i)
再带入f数组转化一下。
这个式子= nd=1f(nd)
因为 nd=2f(nd)+f(n)=(n+1)n/2
所以 f(n)=(n+1)n/2nd=2f(nd)
然后再分块一下。
注意开long long就好了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=5000007,mo=1000000007,moo=878777;
const int ni=500000004;
typedef long long ll;
ll i,j,k,l,t,n,m;
ll chang[moo+1],a[maxn+1],ans,last[moo+1];
int first[moo+1],next[moo+1],phi[maxn+1],p[maxn+1],num;
bool bz[maxn+1];
void add(int x,int y,ll z){
    last[++num]=y;next[num]=first[x];first[x]=num;chang[num]=z;
}
ll suan(ll x){
    ll k=0,l=2,r;ll j=x%moo,i;
    if(x<=maxn)return a[x];
    rep(i,j)if(last[i]==x)return chang[i]; 
    while(l<=x){
        r=x/(x/l);(k+=(r-l+1)%mo*suan(x/l)%mo)%=mo;l=r+1;
    }
    k=(x%mo*(x%mo+1)%mo*ni%mo-k+mo)%mo;
    add(j,x,k);
    return k;
}
int main(){
    phi[1]=1;
    fo(i,2,maxn){
        if(!bz[i])phi[i]=i-1,p[++p[0]]=i;
        fo(j,1,p[0]){
            t=p[j]*i;if(t>maxn)break;bz[t]=1;
            if(!(i%p[j])){phi[t]=phi[i]*p[j];break;}
            phi[t]=phi[i]*(p[j]-1);
        }
    }
    fo(i,1,maxn)(a[i]+=a[i-1]+phi[i])%=mo;
    scanf("%lld",&n);
    ans=suan(n);
    printf("%lld\n",ans);
}

你可能感兴趣的:(欧拉函数,分块,51nod,欧拉函数之和,欧拉函数的性质)