欧拉函数

定义

欧拉函数(Euler's totient function),即 φ(n)\varphi(n),表示的是小于等于 nn 和 nn 互质的数的个数.

比如说 φ(1)=1\varphi(1) = 1.

当 nn 是质数的时候,显然有 φ(n)=n−1\varphi(n) = n - 1.

性质

  • 欧拉函数是 积性函数.

    即对任意满足 gcd⁡(a,b)=1\gcd(a, b) = 1 的整数 a,ba,b,有 φ(ab)=φ(a)φ(b)\varphi(ab) = \varphi(a)\varphi(b).

    特别地,当 nn 是奇数时 φ(2n)=φ(n)\varphi(2n) = \varphi(n).

    证明参见 剩余系的复合.

  • n=∑d∣nφ(d)n = \sum_{d \mid n}{\varphi(d)}.

    ???+ note "证明" 利用 莫比乌斯反演 相关知识可以得出.

    也可以这样考虑:如果 $\gcd(k, n) = d$,那么 $\gcd(\dfrac{k}{d},\dfrac{n}{d}) = 1, ( k < n )$.
    
    如果我们设 $f(x)$ 表示 $\gcd(k, n) = x$ 的数的个数,那么 $n = \sum_{i = 1}^n{f(i)}$.
    
    根据上面的证明,我们发现,$f(x) = \varphi(\dfrac{n}{x})$,从而 $n = \sum_{d \mid n}\varphi(\dfrac{n}{d})$.注意到约数 $d$ 和 $\dfrac{n}{d}$ 具有对称性,所以上式化为 $n = \sum_{d \mid n}\varphi(d)$.
    
  • 若 n=pkn = p^k,其中 pp 是质数,那么 φ(n)=pk−pk−1\varphi(n) = p^k - p^{k - 1}. (根据定义可知)

  • 由唯一分解定理,设 n=∏i=1spikin = \prod_{i=1}^{s}p_i^{k_i},其中 pip_i 是质数,有 φ(n)=n×∏i=1spi−1pi\varphi(n) = n \times \prod_{i = 1}^s{\dfrac{p_i - 1}{p_i}}.

    ???+ note "证明" - 引理:设 pp 为任意质数,那么 φ(pk)=pk−1×(p−1)\varphi(p^k)=p^{k-1}\times(p-1).

        证明:显然对于从 1 到 $p^k$ 的所有数中,除了 $p^{k-1}$ 个 $p$ 的倍数以外其它数都与 $p^k$ 互素,故 $\varphi(p^k)=p^k-p^{k-1}=p^{k-1}\times(p-1)$,证毕.
    
    接下来我们证明 $\varphi(n) = n \times \prod_{i = 1}^s{\dfrac{p_i - 1}{p_i}}$.由唯一分解定理与 $\varphi(x)$ 函数的积性
    
    $$
    \begin{aligned}
        \varphi(n) &= \prod_{i=1}^{s} \varphi(p_i^{k_i}) \\
        &= \prod_{i=1}^{s} (p_i-1)\times {p_i}^{k_i-1}\\
        &=\prod_{i=1}^{s} {p_i}^{k_i} \times(1 - \frac{1}{p_i})\\
        &=n~ \prod_{i=1}^{s} (1- \frac{1}{p_i})
        &\square
    \end{aligned}
    $$
    
  • 对任意不全为 00 的整数 m,nm,n,φ(mn)φ(gcd⁡(m,n))=φ(m)φ(n)gcd⁡(m,n)\varphi(mn)\varphi(\gcd(m,n))=\varphi(m)\varphi(n)\gcd(m,n).

    可由上一条直接计算得出.

实现

如果只要求一个数的欧拉函数值,那么直接根据定义质因数分解的同时求就好了.这个过程可以用 Pollard Rho 算法优化.

参考实现

C++

#include <cmath>

int euler_phi(int n) {
  int ans = n;
  for (int i = 2; i * i <= n; i++)
    if (n % i == 0) {
      ans = ans / i * (i - 1);
      while (n % i == 0) n /= i;
    }
  if (n > 1) ans = ans / n * (n - 1);
  return ans;
}

Python

import math


def euler_phi(n):
    ans = n
    for i in range(2, math.isqrt(n) + 1):
        if n % i == 0:
            ans = ans // i * (i - 1)
            while n % i == 0:
                n = n // i
    if n > 1:
        ans = ans // n * (n - 1)
    return ans

如果是多个数的欧拉函数值,可以利用后面会提到的线性筛法来求得.

详见:筛法求欧拉函数

应用

欧拉函数常常用于化简一列最大公约数的和.国内有些文章称它为 欧拉反演1.

在结论

n=∑d∣nφ(d)n=\sum_{d|n}\varphi(d)

中代入 n=gcd⁡(a,b)n=\gcd(a,b),则有

gcd⁡(a,b)=∑d∣gcd⁡(a,b)φ(d)=∑d[d∣a][d∣b]φ(d),\gcd(a,b) = \sum_{d|\gcd(a,b)}\varphi(d) = \sum_d [d|a][d|b]\varphi(d),

其中 [⋅][\cdot] 为 Iverson 括号.对上式求和,就可以得到

∑i=1ngcd⁡(i,n)=∑d∑i=1n[d∣i][d∣n]φ(d)=∑d⌊nd⌋[d∣n]φ(d)=∑d∣n⌊nd⌋φ(d).\sum_{i=1}^n\gcd(i,n)=\sum_{d}\sum_{i=1}^n[d|i][d|n]\varphi(d)=\sum_d\left\lfloor\frac{n}{d}\right\rfloor[d|n]\varphi(d)=\sum_{d|n}\left\lfloor\frac{n}{d}\right\rfloor\varphi(d).

这里关键的观察是 ∑i=1n[d∣i]=⌊nd⌋\sum_{i=1}^n[d|i]=\lfloor\frac{n}{d}\rfloor,即在 11 和 nn 之间能够被 dd 整除的 ii 的个数是 ⌊nd⌋\lfloor\frac{n}{d}\rfloor.

利用这个式子,就可以遍历约数求和了.需要多组查询的时候,可以预处理欧拉函数的前缀和,利用数论分块查询.

GCD SUM

给定 n≤100000n\le 100000,求

∑i=1n∑j=1ngcd⁡(i,j).\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j).
思路

仿照上文的推导,可以得出

∑i=1n∑j=1ngcd⁡(i,j)=∑d=1n⌊nd⌋2φ(d).\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j) = \sum_{d=1}^n\left\lfloor\frac{n}{d}\right\rfloor^2\varphi(d).

此时需要从 11 遍历到 nn 求欧拉函数,用线性筛做就可以 O(n)O(n) 得到答案.

欧拉定理

与欧拉函数紧密相关的一个定理就是欧拉定理.其描述如下:

若 gcd⁡(a,m)=1\gcd(a, m) = 1,则 aφ(m)≡1(modm)a^{\varphi(m)} \equiv 1 \pmod{m}.

扩展欧拉定理

当然也有扩展欧拉定理,用于处理一般的 aa 和 mm 的情形.

ab≡{ab mod φ(m), gcd⁡(a, m)=1ab,gcd⁡(a, m)≠1, b<φ(m)ab mod φ(m)+φ(m),gcd⁡(a, m)≠1, b≥φ(m)(modm)a^b\equiv \begin{cases} a^{b\bmod\varphi(m)},\,&\gcd(a,\,m)=1\\ a^b,&\gcd(a,\,m)\ne1,\,b<\varphi(m)\\ a^{b\bmod\varphi(m)+\varphi(m)},&\gcd(a,\,m)\ne1,\,b\ge\varphi(m) \end{cases} \pmod m

证明和习题详见 欧拉定理.

习题

参考资料与注释

Footnotes

  1. 这一说法并未见于学术期刊或国外的论坛中,在使用该说法时应当注意. ↩

本文内容来自 OI Wiki《欧拉函数》;作者与修订历史见原文。AIOJ 对排版、站内链接和资源路径做了格式适配。

内容依 CC BY-SA 4.0 与 SATA 许可共享;附加条款以原文声明为准。感谢 OI Wiki 作者与贡献者;请按 SATA 约定前往 OI Wiki 仓库 Star 支持。