BZOJ 4805: 欧拉函数求和 杜教筛
https://www.lydsy.com/JudgeOnline/problem.php?id=4805
给出一个数字N,求sigma(phi(i)),1<=i<=N
https://blog.csdn.net/popoqqq/article/details/45023331 ←杜教筛的一些讲解
杜教筛用来求积性函数前缀和,本题同bzoj 3944,bzoj 3944多了一个求sigma( μ ( i ) )
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 #define LL long long 9 const int maxn=5000010; 10 LL n; 11 LL phi[maxn]={}; 12 LL pri[maxn/10]={},tot=0; 13 bool v[maxn]={}; 14 void get_phi(int m){ 15 phi[1]=1; 16 for(int i=2;i<=m;++i){ 17 if(!v[i]){pri[++tot]=i;phi[i]=i-1;} 18 for(int j=1;j<=tot&&pri[j]*i<=m;++j){ 19 int w=pri[j]*i;v[w]=1; 20 if(i%pri[j]==0){phi[w]=phi[i]*pri[j];break;} 21 phi[w]=phi[i]*(pri[j]-1); 22 } 23 } 24 //for(int i=1;i<=10;++i)cout<<phi[i]<<endl; 25 for(int i=1;i<=m;++i){ 26 phi[i]+=phi[i-1]; 27 } 28 } 29 LL solve(LL m){ 30 if(m<=maxn-10)return phi[m]; 31 LL ans=m*(m+1)/2; 32 for(LL i=2,las;i<=m;i=las+1){ 33 las=m/(m/i); 34 ans-=(LL)(las-i+1)*solve(m/i); 35 } 36 return ans; 37 } 38 int main(){ 39 get_phi(maxn-10); 40 scanf("%lld",&n); 41 printf("%lld\n",solve(n)); 42 return 0; 43 }