欧拉函数
http://www.cnblogs.com/exponent/archive/2011/08/09/2131960.html
设n为正整数,以 φ(n)表示不超过n且与n互素的正整数的个数,称为n的欧拉函数值
φ:N→N,n→φ(n)称为欧拉函数
φ函数的值 通式:φ(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 (注意:每种质因数只一个。比如12=2*2*3那么φ(12)=12*(1-1/2)*(1-1/3)=4
欧拉函数用希腊字母φ表示,φ(N)表示N的欧拉函数.
它又称为Euler'stotientfunction、φ函数、欧拉商数等。例如φ(8)=4,因为1,3,5,7均和8互质
性质:
1.欧拉函数是积性函数,但不是完全积性函数,即φ(mn)=φ(n)*φ(m)只在(n,m)=1互质时成立.
2.对于一个正整数N的素数幂分解N=P1^q1*P2^q2*...*Pn^qn.
φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn).
3.除了N=2,φ(N)都是偶数.
4.设N为正整数,∑φ(d)=N (d|N).
根据性质2,我们可以在O(sqrt(n))的时间内求出一个数的欧拉函数值.
特殊性质:当n为奇数时,φ(2n)=φ(n)
求欧拉函数值:
1 #include "iostream" 2 #include "cstdio" 3 using namespace std; 4 #define LL long long 5 LL phi(LL n)///求n的欧拉函数 6 { 7 LL temp=n; 8 for(LL i=2;i*i<=n;i++) 9 if(n%i==0) //找n的质因子 10 { 11 while(n%i==0)n/=i; 12 temp=temp/i*(i-1); 13 } 14 if(n!=1)temp=temp/n*(n-1); 15 return temp; 16 } 17 int main() 18 { 19 LL n; 20 while(~scanf("%I64d",&n)&&n) 21 { 22 printf("%I64d\n",phi(n)); 23 } 24 return 0; 25 }
http://poj.org/problem?id=2407
1 #include "iostream" 2 #include "string" 3 #include "cstdio" 4 #include "cstdlib" 5 using namespace std; 6 int gcd(int a,int b) 7 { 8 return b==0?a:gcd(b,a%b); 9 } 10 int el1(int n) 11 { 12 int Count=0; 13 for(int i=n;i>0;i--) 14 { 15 if(gcd(n,i)==1)///计算个数o(n) 16 { 17 Count++; 18 } 19 } 20 return Count; 21 } 22 23 int main() 24 { 25 int n; 26 while(~scanf("%d",&n)&&n) 27 { 28 cout<<el1(n)<<endl; 29 } 30 }
Time Limit Exceeded
1 #include "iostream" 2 #include "string" 3 #include "cstdio" 4 #include "cstdlib" 5 using namespace std; 6 7 #include "cmath" 8 9 const int NUM=1000000001; 10 int p[NUM]; 11 void prime() 12 { 13 p[0]=p[1]=1; 14 int i=2,j=0; 15 for(i=2;i<NUM;i++) 16 { 17 if(p[i]==0) 18 { 19 for(j=i+i;j<NUM;j+=i){ 20 p[j]=1; 21 } 22 } 23 } 24 } 25 26 double el2(int n)///欧拉公式 27 { 28 double sum=n; 29 if(p[n]==0) 30 { 31 return sum-1; 32 } 33 else 34 { 35 int i=2; 36 while(n>1) 37 { 38 if(p[i]==0) 39 { 40 int j=0; 41 while(n%i==0) 42 { 43 if(j==0) 44 { 45 sum=sum*(1-1.0/i); 46 j++; 47 } 48 n/=i; 49 } 50 } 51 i++; 52 } 53 return sum; 54 } 55 } 56 int main() 57 { 58 int n; 59 prime(); 60 while(~scanf("%d",&n)&&n) 61 { 62 cout<<el2(n)<<endl; 63 } 64 }
Runtime Error
1.关于本题:分解为素数乘积时,潜在的范围,2->sqrt(n),
另外不用判断是否为素数,从2开始除的必定都是素数
2.关代码 摘自http://www.cnblogs.com/neopenx/p/4095268.html
学习!!!1.C++ STL 2.#define LL long long 3.规范(命名)
正解:
1 #include "cstdio" 2 #include "map" 3 using namespace std; 4 #define LL long long 5 map<LL,LL> prime_factor(LL n) 6 { 7 map<LL,LL> res; 8 for(int i=2;i*i<=n;i++) 9 while(n%i==0) {++res[i];n/=i;}//res键重复 覆盖 10 if(n!=1) res[n]=1; 11 return res; 12 } 13 int main() 14 { 15 LL n; 16 while(scanf("%I64d",&n)!=EOF&&n) 17 { 18 if(n==1) {printf("1\n");continue;} 19 map<LL,LL> fac=prime_factor(n); 20 LL ret=n; 21 for(map<LL,LL>::iterator i=fac.begin();i!=fac.end();i++) 22 ret=ret/i->first*(i->first-1);//first是Key, second是value; 提取从头到尾的键参与运算 23 printf("%I64d\n",ret); 24 } 25 }