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 }
View Code

 

posted @ 2018-06-26 18:22  鲸头鹳  阅读(187)  评论(0编辑  收藏  举报