欧拉函数
代码模板欧拉函数 $\varphi(n)$ 统计 $1$ 到 $n$ 中有多少个数与 $n$ 互质。
一句话算法
欧拉函数
问题模型
给定一个正整数
例如
核心直觉
一个数
如果:
那么要从
注意,公式只关心“有哪些不同质因子”,不关心每个质因子的次数。
算法步骤
- 令答案
ans = n。 - 从
p = 2开始试除到。 - 如果
p能整除当前n:- 说明
p是原数的一个质因子; - 更新
ans = ans / p * (p - 1); - 把当前
n中所有因子p除干净。
- 说明
- 循环结束后,如果
n > 1,说明剩下一个大质因子,再做一次:ans = ans / n * (n - 1)。
- 输出
ans。
算法证明
设
-
不互质的判定
与 不互质,等价于 至少含有一个 作为因子。 -
保留下来的比例
在
中, 的倍数占 。删掉这些倍数后,保留比例为: -
多个质因子的容斥
对所有不同质因子做容斥,保留下来的数量为:
-
代码等价
对每个质因子
,代码执行: 这正是把当前答案乘上
的整数写法。
所以算法正确计算了
复杂度分析
试除法最多枚举到
空间复杂度为
如果需要求
代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h>
using namespace std;
long long euler_phi(long long n) {
long long ans = n;
for (long long p = 2; p * p <= n; p++) {
if (n % p != 0) continue;
ans = ans / p * (p - 1);
while (n % p == 0) n /= p;
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n;
cin >> n;
cout << euler_phi(n) << '\n';
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 欧拉函数 φ(n):1..n 中与 n 互质的数的个数,先试除分解质因数,再按
# φ(n) = n * Π (p - 1) / p 累乘(每步先除后乘,避免中间结果变大)。
# 边界:n = 1 返回 1;n = 0 返回 0;n < 0 时直接返回 n,与 C++ 版一致(调用方保证 n >= 1)。
# C++ 的 p * p <= n 在 p 接近 long long 上限时会溢出;Python int 任意精度。
def euler_phi(n: int) -> int:
ans = n
p = 2
# 注意 n 在循环里会被不断除掉已找到的质因子,所以 p * p <= n 用的是缩小后的 n。
while p * p <= n:
if n % p != 0:
p += 1
continue
ans = ans // p * (p - 1)
while n % p == 0:
n //= p
p += 1
# 循环结束后剩下的 n > 1 说明它本身是一个质因子。
if n > 1:
ans = ans // n * (n - 1)
return ans
测试用例
输入:
36
输出:
12
解释:
所以:
应用分类详解
欧拉函数的本质是统计模
一、互质计数
典型模式: 题目要求统计
识别信号: 出现“互质个数”“小于等于 n 且 gcd 为 1”。
核心建模: 把
| 应用场景 | 经典题目 | 核心思路 |
|---|---|---|
| 单点互质计数 | luogu-P2303 | 试除质因子求 |
| 互质对统计 | luogu-P2158 | 枚举分母时用欧拉函数计数 |
二、模意义下的可逆元素
典型模式: 判断模
识别信号: 出现“逆元”“剩余类”“与模数互质”。
核心建模: 模
| 应用场景 | 经典题目 | 核心思路 |
|---|---|---|
| 逆元存在性 | 模运算题 | gcd(a,n)=1 才存在逆元 |
| 剩余类群大小 | 数论证明题 | 可逆剩余类个数为 |
三、欧拉定理与指数降幂
典型模式: 大指数取模,并且底数与模数互质。
识别信号: 出现
核心建模: 若
可以用
| 应用场景 | 经典题目 | 核心思路 |
|---|---|---|
| 欧拉降幂 | 大指数取模题 | 先求 |
| 费马小定理 | 素数模数题 | 素数 |
经典例题
1. luogu-P2303
单个数欧拉函数模板题。分解 ans = ans / p * (p - 1)。
2. luogu-P2158
统计互质点对。核心是把每个分母对应的合法分子数量转化为欧拉函数值。
3. 欧拉降幂类题
当题目要求计算超大指数的
参考
- 欧拉函数公式
- 欧拉定理