Skip to content

欧拉函数

欧拉函数的定义:1n 中与 n 互质的数的个数被称为 n 的欧拉函数,记为 ϕ(n)。例如 ϕ(6)=2

根据算术基本定理,n 可以写成所有质因数的乘积:

n=p1α1p2α2pmαm,

欧拉函数的性质:

  • ϕ(1)=1
  • 如果 p 是质数,那么 ϕ(p)=p1
  • 如果 n=pk 是质数的次方,那么 ϕ(n)=pkpk1
    • 这是因为和 n 互质的数一定不是 p 的倍数
    • p 的倍数有 p,2p,,pk1×p 共计 pk1
  • 如果 n 可以分解为两个互质整数乘积,那么 ϕ(n)=ϕ(pq)=ϕ(p)ϕ(q)
    • 注意这里的两个整数是互质的,不一定是质数
    • TODO:中国剩余定理证明

欧拉函数的计算:

ϕ(n)=n(11p1)(11p2)(11pk)

证明:容斥原理:

  • 1n 中去掉所有 p1,p2,,pk 的倍数
  • 上一步删除了很多重复元素,这一步加上 p1p2,p1p3,,pk1pk 的倍数
  • 循环往复……
ϕ(n)=nnp1np2npk+np1p2+=nni=1k1pi+nijk1pipj=n(1+i=1n1j1<j2<<jin(1)i1pj1pj2pj3pji)

我们可以看到系数只有正负一两种,而偶数个质因子作为分母都是 -1,奇数个质因子作为分母则是 +1,二者一致,因此公式是正确的。

算法的时间复杂度瓶颈在于对 n 分解质因数,得到质因数后 O(1) 就可以算出来。

AC873. 欧拉函数

线性筛求欧拉函数

给定一个正整数 n,可以在 O(n) 的时间内求出 1n 的欧拉函数(注意上一个是用 O(n) 时间求出了正整数 n 的欧拉函数)

AC874. 筛法求欧拉函数

这里注意一个细节:6210×320 除去 n 后面两个括号里的东西是一样的都是 1/3

核心代码:

cpp
void get_euler(int n) {
    phi[1] = 1;

    for (int i = 2; i <= n; i ++) {
        if (!st[i]) {
            primes[cnt ++] = i;

            phi[i] = i - 1;
        }

        for (int j = 0; primes[j] <= n / i; j ++) {
            st[primes[j] * i] = true;

            if (i % primes[j] == 0) {
                phi[primes[j] * i] = phi[i] * primes[j];
                break;
            }
            else {
                phi[primes[j] * i] = phi[i] * (primes[j] - 1); 
            }
        }
    }
}

if (i % primes[j] == 0) 没有判定 break 之前,进入该循环的数都是刚用最小质因子筛掉的合数。具体可以参见 31-质数 中的线性筛一节。

  • phi[primes[j] * i] = phi[i] * primes[j];:公式
  • phi[primes[j] * i] = phi[i] * (primes[j] - 1); :积性

欧拉定理

a,nN,且二者互质,则有:

aϕ(n)1(modn)

证明:对于 1n 中,有 ϕ(n) 个和 n 互素的数,记为:

a1,a2,,aϕ(n)

可以证明,aai 也是(模 n 意义下)互不相同的 ϕ(n) 个数。这里用到反证法,假设 aaiaaj(modn),那么 a(aiaj)0(modn)。由于 a,n 互质,因此有 aiaj(modn),这里由于 ai<n,aj<n,因此得出 ai=aj,矛盾。

而由于 aain 互质,因此所有的 aai 构成了模 n简化剩余系,是完全剩余系中与 n 互素的数构成的子集。显然,a1,a2,,aϕ(n) 正是模 n 的简化剩余系。因此:

aϕ(n)(a1a2aϕ(n))a1a2aϕ(n)(modn)

由于 a1a2aϕ(n)n 互质,因此:

aϕ(n)1(modn)

得证。

Released under the MIT License.