天天看点

欧拉φ函数

欧拉φ函数

这是我看过某同学写的之后,应为感觉自己要用所以自己摘要了一下下,

哪里写错了的地方,或哪里有意见不一致的地方还请各位路过的帮忙给改改

谢谢帮助.........

φ(n)是所有小于n的正整数里,和n互素的整数的个数。n是一个正整数。

如果n的标准素因子分解式是p1^a1*p2^a2*……*pm*am,其中众pj(j=1,2,……,m)都是素数,而且两两不等。则有

φ(n)=n(1-1/p1)(1-1/p2)……(1-1/pm)

性质

根据Fermat-Euler定理:

对任何两个互质的正整数a, m, m>=2有

a^φ(m)≡1(mod m)

当m是质数p时,此式则为

a^(p-1)≡1(mod m)

若m=m1*m2*m3*......*mk,而m1,m2,m3......mk两两互质,

则φ(m)=φ(m1)*φ(m2)*φ(m3)*φ(m4)......*φ(mk)。

a为质数

若(N % a==0 && (N/a)%a==0) 则有

φ(n) = φ(n/a)*a

若(N % a==0 && (N/a)%a!=0) 则有:

φ(n) = φ(n/a)*(a-1)

int euler(int n){
     int m = n, i;
     if(n % 2 == 0) m /= 2;
     while(n % 2 == 0) n /= 2;
     for(i = 3; n != 1; i += 2){
         if(n % i == 0) m -= m / i;
         while(n % i == 0) n /= i;
     }
     return m;
 }      
const int maxn = 40000;
 bool pf[maxn];
 int p[maxn], numOfP = 0;
 void init(){
     memset(pf, 0, sizeof(pf));
     for(int i = 2; i < maxn; i++){
         if(!pf[i]){
             p[numOfP++] = i;
             for(int j = i * i; j < maxn; j += i)
                 pf[j] = true;
         }
     }
 }
 int euler1(int n){
     int sum = 1;
     int tmp;
     for(int i = 0; i < numOfP; i++){
         if(n == 1) break;
         if(n % p[i] == 0){
             tmp = 0;
             while(n % p[i] == 0){
                 n /= p[i];
                 tmp++;
             }
             for(int j = 1; j < tmp; j++)
                 sum *= p[i];
             sum *= p[i] - 1;
         }
     }
     if(n == 1)
         return sum;
     else
         return sum * (n - 1);
 }
 int euler2(int n)
 {
     int i;
     for(i = 2; i <= sqrt((double)n); i++){
         if(n % i == 0 && !pf[i]){
             n /= i;
             if(n % i ==0)
                 return i * euler2(n);
             else
                 return (i - 1) * euler2(n);
         }
     }
     return n-1;
 }