欧拉函数

走远了吗. 提交于 2020-04-04 03:54:08

一、质因数与分解质因数 ?
如果一个质数是某个数的约数,那么就说这个质数是这个数的质因数。 
把一个合数用质因数相乘的形式表示出来,叫做分解质因数。 
例:把30分解质因数。 
解:30=2×3×5。 
其中2、3、5叫做30的质因数。 
又如12=2×2×3=22×3,2、3都叫做12的质因数。
二、 公约数只有1的两个数,叫做互质数
(欧拉函数是小于n的正整数中与n互质的数的数目)

列:1到8中 ,与8互质的数有:1、3、 5、 7

1到12中,与12互质的数有: 1、 5、 7、 11、

 

看了一下午的欧拉函数,感觉都快看崩溃了,还好找到一个看得懂的博客。。。。

https://www.cnblogs.com/linyujun/p/5194170.html

欧拉函数,用φ(n)表示


欧拉函数是求小于等于n的数中与n互质的数的数 
可以先在1到n-1中找到与n不互质的数,然后把他们减掉
 比如φ(12)
把12质因数分解,12=2*2*3,其实就是得到了2和3两个质因数
然后把2的倍数和3的倍数都删掉
2的倍数:2,4,6,8,10,12
3的倍数:3,6,9,12

本来想直接用12 - 12/2 - 12/3
但是6和12重复减了
所以还要把即是2的倍数又是3的倍数的数加回来 (>﹏<)
所以这样写12 - 12/2 - 12/3 + 12/(2*3)
这叫什么,这叫容斥啊,容斥定理听过吧
比如φ(30),30 = 2*3*5
所以φ(30) = 30 - 30/2 - 30/3 - 30/5 + 30/(2*3) + 30/(2*5) + 30/(3*5) - 30/(2*3*5)
但是容斥写起来好麻烦( ̄. ̄)
有一种简单的方法
φ(12)   =   12*(1 - 1/2)*(1 - 1/3)                 =   12*(1 - 1/2 - 1/3 + 1/6)

 

φ(30)   =   30*(1 - 1/2)*(1 - 1/3)*(1 - 1/5)   =   30*(1 - 1/2 - 1/3 - 1/5 + 1/6 + 1/10 + 1/15 - 1/30)

 

你看她都帮你容斥好了

所以φ(30)的计算方法就是先找30的质因数

 

分别是2,3,5
然后用30* 1/2 * 2/3 * 4/5就搞定了

 

顺便一提,phi(1) = 1

代码如下:

复制代码

 1 //欧拉函数
 2 int phi(int x){
 3     int ans = x;
 4     for(int i = 2; i*i <= x; i++){
 5         if(x % i == 0){
 6             ans = ans / i * (i-1);
 7             while(x % i == 0) x /= i;
 8         }
 9     }
10     if(x > 1) ans = ans / x * (x-1);
11     return ans;
12 }

复制代码

(phi就是φ的读音)

机智的代码,机智的我(。・`ω´・)

 这个的复杂度是O(√n),如果要你求n个数的欧拉函数,复杂度是O(n√n),这也太慢了

 有更快的方法

跟埃筛素数差不多

#include<cstdio>
const int N = 100000 + 5;
int phi[N];
void Euler(){
    phi[1] = 1;
    for(int i = 2; i < N; i ++){
        if(!phi[i]){
            for(int j = i; j < N; j += i){
                if(!phi[j]) phi[j] = j;
                phi[j] = phi[j] / i * (i-1);
            }
        }
    }
}
int main(){
    Euler();
}

 

(Euler就是欧拉)

 

另一种,比上面更快的方法

需要用到如下性质

p为质数

1. phi(p)=p-1   因为质数p除了1以外的因数只有p,故1至p的整数只有p与p不互质 

2. 如果i mod p = 0, 那么 phi(i * p)=phi(i) * p         (我不会证明)

3.若i mod p ≠0,  那么 phi( i * p )=phi(i) * ( p-1 )   (我不会证明)

 

#include<cstdio>
using namespace std;
const int N = 1e6+10 ;
int phi[N], prime[N];
int tot;//tot计数,表示prime[N]中有多少质数 
void Euler(){
    phi[1] = 1;
    for(int i = 2; i < N; i ++){
        if(!phi[i]){
            phi[i] = i-1;
            prime[tot ++] = i;
        }
        for(int j = 0; j < tot && 1ll*i*prime[j] < N; j ++){
            if(i % prime[j]) phi[i * prime[j]] = phi[i] * (prime[j]-1);
            else{
                phi[i * prime[j] ] = phi[i] * prime[j];
                break;
            }
        }
    }
}
 
int main(){
    Euler();
}

 

最后说下

 

a^b % p  不等价  (a%p)^(b%p) % p
因为
a^φ(p) ≡ 1 (mod p)
所以
a^b % p  =  (a%p)^(b%φ(p)) % p
(欧拉函数前提是a和p互质)
欧拉求余1
如果p是质数

直接用这个公式


欧拉求余2
 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!