【题目大意】
求∑φ(i)(1<=i<=N)。
【思路】
欧拉函数具有如下的重要推论:
当b是素数时
性质①若b|a,有φ(ab)=φ(a)*b;
性质②若b不|a,有φ(ab)=φ(a)*(b-1)。
由此可以得出递推求欧拉函数表的方法:
对于当前φ(i),若未被修改过,这说明它是素数,加入素数表。
对于每个i,枚举小于它的所有素数j。利用性质1和性质2求出φ(ij)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int MAXN=1000000+50; 8 typedef long long ll; 9 int n,maxn; 10 int phi[MAXN],p[MAXN],input[MAXN]; 11 ll s[MAXN]; 12 int t=0; 13 14 void eular_table() 15 { 16 memset(phi,0,sizeof(phi)); 17 memset(p,0,sizeof(p)); 18 p[0]=1;p[1]=2;phi[2]=1; 19 for (int i=2;i<=maxn;i++) 20 { 21 if (phi[i]==0) 22 { 23 p[++p[0]]=i; 24 phi[i]=i-1; 25 } 26 for (int j=1;j<=p[0];j++) 27 { 28 if (i*p[j]<=maxn) phi[i*p[j]]=(i%p[j]==0)? phi[i]*p[j] : phi[i]*(p[j]-1); 29 //注意一定要保证i*p[j]没有超出数组上界,否则RE 30 else break; 31 } 32 } 33 } 34 35 void printans() 36 { 37 s[0]=0; 38 for (int i=1;i<=maxn;i++) 39 s[i]=s[i-1]+phi[i]; 40 for (int i=0;i<t;i++) 41 printf("%lld ",s[input[i]]); 42 } 43 44 int main() 45 { 46 while (~scanf("%d",&n) && n!=0) 47 { 48 input[t++]=n; 49 maxn=max(maxn,n); 50 } 51 eular_table(); 52 printans(); 53 return 0; 54 }