【BZOJ4805】歐拉函數求和
阿新 • • 發佈:2018-11-24
var clas NPU man stream pan display getc 函數
題面
Description
給出一個數字N,求\(\sum\limits_{i=1}^n\varphi(i)\)i,1<=i<=N
Input
正整數N。N<=2*10^9
Output
輸出答案。
Sample Input
10
Sample Output
32
題目分析
杜教篩模板題。
由\((1*\varphi)=Id\),取\(g(x)=1\)。
\[
S(n)=\frac {n \cdot (n+1)}2-\sum_{i=2}^nS(\frac ni)
\]
代碼實現
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<cstdio> #include<iomanip> #include<cstdlib> #include<map> #define MAXN 0x7fffffff typedef long long LL; const int N=1e7+5,M=1e7; using namespace std; inline int Getint(){register int x=0,f=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*f;} bool vis[N]; int prime[N]; LL phi[N]; map<LL,LL>sphi; LL Sphi(int x){ if(x<=M)return phi[x]; if(sphi[x])return sphi[x]; LL ret=1ll*x*(x+1)/2; for(int l=2,r;l<=x;l=r+1){ r=x/(x/l); ret-=(r-l+1)*Sphi(x/l); } return sphi[x]=ret; } int main(){ phi[1]=1; for(int i=2;i<=M;i++){ if(!vis[i])prime[++prime[0]]=i,phi[i]=i-1; for(int j=1;j<=prime[0]&&1ll*prime[j]*i<=M;j++){ vis[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } for(int i=2;i<=M;i++)phi[i]+=phi[i-1]; int n=Getint(); cout<<Sphi(n); return 0; }
【BZOJ4805】歐拉函數求和