欧拉函数

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 }

 

posted @ 2017-03-01 23:46  kimsimple  阅读(749)  评论(0编辑  收藏  举报