欧拉函数

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

推导证明

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

 

命题1:φ(1)=1

证明:无

 

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

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

 

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

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

$$ \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)外的其余列全部从矩阵中移除。

而对于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

 

转载于:https://www.cnblogs.com/dalt/p/8421612.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值