欧拉函数

  欧拉函数φ(x)表示小于等于x的正整数中与x互质的数的个数。好比φ(4)=2,由于4与1,3互质。编程

推导证实

  下面说明欧拉函数的性质,再经过性质得出欧拉函数的公式。函数

 

命题1:φ(1)=1spa

证实:无code

 

命题2:对于任意素数p,φ(p)=p-1blog

证实:每一个素数的因子只有1和自身,故1,2,...,p中有1,2,...,p-1与p互质。it

 

命题3:欧拉函数是积性函数,即对任意互质的正整数n,m,有φ(nm)=φ(n)φ(m)。class

证实:咱们将1~nm之间的正整数以矩阵形式展开:im

$$ \left[\begin{matrix} 1 & 2 &\cdots & m-1 & m\\ m+1 & m+2 &\cdots & 2m-1 & 2m\\ \vdots &\vdots &\ddots &\vdots &\vdots\\ \left(n-2\right)m+1 &\left(n-2\right)m+2 &\cdots &\left(n-1\right)m-1 &\left(n-1\right)m\\ \left(n-1\right)m+1 &\left(n-1\right)m+1 &\cdots & nm-1 & nm \end{matrix}\right] $$集合

对于rm+c,其中1<=r<=n,1<=c<=m,若是c与m互质,那么rm+c则与m互质(同余定理),故咱们能够找到φ(m)个数c1,c2,...,cφ(m),而其他1~m中的正整数因为与m有公约数,故与mn也必然有公约数,即不可能与mn互质。咱们将除了c1,c2,...,cφ(m)外的其他列所有从矩阵中移除。di

而对于c,m+c,...,(n-1)m+c,考虑到m与n互质,所以这里列出的n个数在模n剩余类环中均不一样。事实上im+c=jm+c(mod n),有(i-j)m=0(mod n),而m与n互质,故i-j=kn,这里的i,j取值范围为0~(n-1),故i=j,所以这n个数在模n的意义下两两不一样。而考虑到模n剩余类环的大小为n,所以这n个数刚好组成了整个环,即集合为{1,2,...,n-1}。考虑与n互质的φ(n)个数,r1,r2,...,rφ(n),咱们发现每一列中都有且只有φ(n)个数与n互质。咱们将每一列不能与n互质的数移去,这样总共留下了φ(n)φ(m)个数。

按照上面的说明咱们得知最多只有φ(n)φ(m)个数与mn互质,而咱们还须要保证矩阵中留下的φ(n)φ(m)个数都能与mn互质。考虑与mn非互质的数x,则mn与x有公约数p,即p|mn,考虑到m与n互质,所以或者p|m或者p|n,即x与m或n非互质。考虑到咱们上面的过程将全部与m或n非互质的数所有移除掉了,所以矩阵中留下的数全都与mn互质。

 

命题4:对于任意素数p,φ(p^n)=(p^n)*(1-1/p)。

证实:在p^n中,能与p非互质的数为p,2p,...,p^n,共p^(n-1)个。所以咱们获得φ(p^n)=p^n-p^(n-1)=(p^n)*(1-1/p)。

 

结合上面四条命题,对于任意一个数n,咱们能够将其分解为素因子的幂的乘积$ n=p_1^{c_1}\cdots p_k^{c_k} $(算术基本定理),以后利用命题4与3推出:

$$ \varphi\left(n\right)=\varphi\left(p_1^{c_1}\right)\cdots\varphi\left(p_k^{c_k}\right)=p_1^{c_1}\left(1-1/p_1\right)\cdots p_k^{c_k}\left(1-1/p_k\right)=n\prod_{i=1}^k{\left(1-\frac{1}{p_i}\right)} $$

编程实现

  计算欧拉函数有两种方式,一种是先预处理出全部素数,以后利用O(√n)的时间复杂度计算出欧拉函数φ(n)。第二种方式是利用欧拉筛在O(N)的时间和空间复杂度内计算1~N之间的全部欧拉函数。前者消耗的空间较少,且时间复杂度在只须要计算少许值的欧拉函数值时有利,然后者则适用于须要计算大批量欧拉函数值且N较小。

  方式1:

phi(n)
    res = n
    for prime p in [1, sqrt(n)]
        if n % p != 0
            continue
        res = res / p * (p - 1)
        while n % p == 0
            n = n / p
    if n > 1 //此时n余下一个素数
        res = res / n * (n  - 1)
    return res

  方式2:

init(limit)
    isPrime = empty-array
    phi = empty-array
    primes = empty-list    
    
    for(i = 1; i < limit; i++)
        isPrime[i] = true
    
    phi[1] = 1
    for(i = 2; i < limit; i++)
        if(isPrime[i]){
            phi[i] = i - 1
            primes.add(i)
        }
        for p in primes
            isPrime[i * p] = false
            if(i % p == 0)
                phi[i * p] = phi[i] * p
                break
            else
                phi[i * p] = phi[i] * phi[p]
    return phi
相关文章
相关标签/搜索