篩法求歐拉函數
求歐拉函數的公式:
φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn為x的所有質因數,x是不為0的整數。φ(1)=1(唯一和1互質的數就是1本身)。
(注意:每種質因數只一個。比如12=2*2*3 那麼φ(12)=12*(1-1/2)*(1-1/3)=4)
這題資料量比較大用普通的歐拉函數肯定逾時。
這裡運用類似素數篩選法的 思想。
http://hi.baidu.com/taincher/item/417652bd28800b412bebe311
設一數組phi[11],賦初值phi[1]=1,phi[2]=2...phi[10]=10;
然後從2開始迴圈,把2的倍數的φ值*(1-1/2),則phi[2]=2*1/2=1,phi[4]=4*1/2=2,phi[6]=6*1/2=3....;
再是3,3的倍數的φ值*(1-1/3),則phi[3]=3*2/3=2,phi[6]=3*2/3=2,phi[9]=.....;
再5,再7...因為對每個素數都進行如此操作,因此任何一個n都得到了φ(n)=n*(1-1/p1)(1-1/p2)....(1-1/pk)的運算
#include<cstdio>#include<cstring>#include<iostream>#define N 3000000int phi[3000005];using namespace std;int main(){int a,b;int i,j;memset(phi,0,sizeof(phi));for(i=2;i<=N;i++)//求素數if(!phi[i])for(j=i+i;j<=N;j+=i)phi[j]=j;for(i=2;i<=N;i++)if(!phi[i]){phi[i]=i-1;//若是素數,則素數的歐拉函數一定是該素數的值-1.for(j=i+i;j<=N;j+=i){phi[j]=phi[j]/i*(i-1);}}while(cin>>a>>b){__int64 sum=0;for(int i=a;i<=b;i++)sum+=phi[i];printf("%I64d\n",sum);}return 0;}