欧拉函数
创建时间:2025-06-03
欧拉函数简介
欧拉函数(Euler's totient function)是数论中的重要知识点,有很多与欧拉函数有关的定理。
定义欧拉函数 \(\varphi(x)\) 表示小于等于 \(x\) 且与 \(x\) 互质的正整数的个数,即满足 \(y \in \N^*,y \le x,\textup{gcd}(x,y)=1\) 的 \(y\) 的个数。
欧拉函数的计算公式
设有 \(x \in \N^*(x \neq 1)\),根据唯一分解定理, \(x\) 一定等于唯一的 \(p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k}\),其中 \(p_i\) 是互不相等质数。则 \(\varphi(x)=x \Pi_{i=1}^k\frac{p_i-1}{p_i}\)。
证明:由 \(x=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k}\) 知 \(x\) 仅有 \(p_1,p_2,p_3,\cdots p_k\) 这 \(k\) 个质因数,所以所有与 \(x\) 互质的数一定与 \(p_1,p_2,p_3,\cdots,p_k\) 中的任意一个数互质,即不是是 \(p_1,p_2,p_3,\cdots p_k\) 中任意一个数的倍数。而每 \(p_i\) 个数中有 \(p_i-1\) 个数不是 \(p_i\) 的倍数,所以 \([1,x]\) 中不是 \(p_1\) 倍数的数有 \(x \times \frac {p_1-1} {p_1}\) 个,不是 \(p_1,p_2\) 中任意一个数的倍数的数有 \(x \times \frac {(p_1-1)} {p_1} \times \frac {p_2-1} {p_2}\) 个,不是 \(p_1,p_2,p_3\) 中任意一个数的倍数的数有 \(x \times \frac {p_1-1} {p_1} \times \frac {p_2-1} {p_2} \times \frac {p_3-1} {p_3}\) 个,不是 \(p_1,p_2,p_3,\cdots,p_k\) 中任意一个数的倍数的数有 \(x \times \frac {p_1-1} {p_1} \times \frac {p_2-1} {p_2} \times \frac {p_3-1} {p_3} \times \cdots \times \frac {p_k-1} {p_k}\) 个,即 \(\varphi(x)=x \times \frac {p_1-1} {p_1} \times \frac {p_2-1} {p_2} \times \frac {p_3-1} {p_3} \times \cdots \times \frac {p_k-1} {p_k}=x \Pi_{i=1}^k\frac{p_i-1}{p_i}\)。
欧拉函数的性质
性质1:对于质数 \(p\),有 \(\varphi(p^n)=p^{n-1}(p-1)\),其中 \(n\) 为任意正整数。
证明:我们知道 \(\textup{gcd}(a,b)=\gcd(b,a \bmod b) = \gcd(a \bmod b, b)\)(证明见欧几里得算法),于是 \(\gcd(x,p) = \gcd(x \bmod p, p)(x \in \N^*)\),所以 \(\gcd(x,p)\) 以 \(p\) 为周期,所以当求出 \(x \in [1,p]\) 内满足 \(\gcd(x,p)=1\) 的 \(x\) 的数量后乘上周期数量即可,又因为 \([1,p^n]\) 内有 \(\frac {p^n} p=p^{n-1}\) 个周期,于是 \([1,p^n]\) 内与 \(p\) 互质的数的个数就是 \(p^{n-1} \varphi(p)=p^{n-1}(p-1)\)。
性质2:对于质数 \(p\),有 \(\varphi(p^n)=p^{n-1}(p-1)\),其中 \(n\) 为任意正整数。
证明:我们知道 \(\gcd(a,b)=\gcd(b,a \bmod b) = \gcd(a \bmod b, b)\)(证明见欧几里得算法),于是 \(\gcd(x,p) = \gcd(x \bmod p, p)(x \in \N^*)\),所以 \(\gcd(x,p)\) 以 \(p\) 为周期,所以当求出 \(x \in [1,p]\) 内满足 \(\gcd(x,p)=1\) 的 \(x\) 的数量后乘上周期数量即可,又因为 \([1,p^n]\) 内有 \(\frac {p^n} p=p^{n-1}\) 个周期,于是 \([1,p^n]\) 内与 \(p\) 互质的数的个数就是 \(p^{n-1} \varphi(p)=p^{n-1}(p-1)\)。
性质3(积性):对于互质的两数 \(n,m\),有 \(\varphi(nm)=\varphi(n)\varphi(m)\)。
证明:令 \(n=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k},m=q_1^{\beta_1}q_2^{\beta_2}q_3^{\beta_3}\cdots q_t^{\beta_t}\),因为 \(n,m\) 互质,所以 \(n,m\) 的质因数不应有重叠,即对于任意 \(1 \le i \le k, 1 \le j \le t\),有 \(p_i \neq q_j\)。而将 \(nm\) 分解质因数后有 \(nm=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k}q_1^{\beta_1}q_2^{\beta_2}q_3^{\beta_3}\cdots q_t^{\beta_t}\),\(p\)、\(q\) 两两不同,所以可以运用欧拉函数计算公式,得:\(\varphi(nm)=nm \times \frac {p_1-1} {p_1} \times \frac {p_2-1} {p_2} \times \frac {p_3-1} {p_3} \times \cdots \times \frac {p_k-1} {p_k}\times \frac {q_1-1} {q_1} \times \frac {q_2-1} {q_2} \times \frac {q_3-1} {q_3} \times \cdots \times \frac {q_k-1} {q_t}=[n \times\frac{p_1-1}{p_1}\times\frac{p_2-1}{p_2} \times\frac{p_3-1}{p_3}\times\cdots\times\frac {p_k-1}{p_k}][m\times\frac{q_1-1}{q_1}\times\frac{q_2-1}{q_2}\times\frac{q_3-1}{q_3}\times\cdots\times\frac{q_k-1}{q_t}]=\varphi(n)\varphi(m)\)。
求解欧拉函数
方法一,枚举:
根据欧拉函数的计算公式,我们可以 \(O(\sqrt x)\) 的枚举 \(x\) 的质因数并套进公式计算,而 \(x\) 的非 \(1\) 最小因数一定是质数,所以可以写出以下代码:
int Euler(int x) {
int ans = 1;
for (int i = 1; i * i <= x; i++)
if (x % i == 0) {
ans = ans / i * (i - 1);
while (x % i == 0)
x /= i;
}
if (x != 1)
ans = ans / x * (x - 1);
return ans;
}
方法二,埃式筛:
既然可以枚举质因数,就一定也能使用埃式筛一次性处理 \(1 \sim n\) 的所有欧拉函数值,思路同样是套公式,复杂度 \(O(n \log \log n)\):
void init(int maxn) {
for (int i = 1; i <= maxn; i++)
phi[i] = i;
for (int i = 2; i <= maxn; i++)
if (phi[i] == i) {
for (int j = i; j <= maxn; j += i)
phi[i] = phi[i] / i * (i - 1);
}
}
方法三,欧拉筛:
既然可以用埃式筛,那可以用欧拉筛吗?答案是肯定的。对于正整数 \(i\) 和质数 \(j\),当 \(i\) 是 \(j\) 的倍数时,\(i\) 分解后的 \(i=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k}\) 中一定有一个 \(p_x=p\),不妨设 \(p_1=p\),则 \(ij=p_1^{\alpha_1+1}p_2^{\alpha_2}p_3^{\alpha_3}\cdots p_k^{\alpha_k},\varphi(i,j)=ij\Pi_{t=1}^k\frac{p_t-1}{p_t}=[i\Pi_{t=1}^k\frac{p_t-1}{p_t}]\times j=\varphi(i) \times j\);当 \(i\) 不是 \(j\) 的倍数,即 \(i,j\) 互质时,可以利用欧拉函数的积性得到 \(\varphi(ij)=\varphi(i)\varphi(j)\)。由于每个数只被它的最小质数筛掉,所以时间复杂度为 \(O(n)\),代码如下:
void init(int maxn) {
phi[1] = 1;
for (int i = 2; i <= maxn; i++) {
if (phi[i] == 0) {
phi[i] = i - 1;
primes.emplace_back(i);
}
for (int j : primes) {
if (i * j >= maxn)
break;
if (i % j == 0) {
phi[i * j] = phi[i] * j;
break;
} else
phi[i * j] = phi[i] * phi[j];
}
}
}

浙公网安备 33010602011771号