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(a−1)
由于与莫比乌斯函数之和类似,脑袋O(1)得解。
∑d|nφ(d)=n​​关于欧拉函数的一个性质​​
∑ni=1∑d|iφ(d)=(n+1)∗n/2
熟练掌握内层外移的话,这种东西只可以转化的。
这个式子=∑nd=1∑ndi=1φ(i)
再带入f数组转化一下。
这个式子=∑nd=1f(nd)
因为∑nd=2f(nd)+f(n)=(n+1)∗n/2
所以f(n)=(n+1)∗n/2−∑nd=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);
}