线性筛和欧拉函数
1. 定义与用途
概念 | 定义 | 用途 |
---|---|---|
线性筛 | 一种时间复杂度为 O(n) 的算法,用于高效筛选出所有小于等于 n 的素数。 | 生成素数表、辅助计算数论函数(如欧拉函数、莫比乌斯函数)。 |
欧拉函数 ϕ(n)ϕ(n) | 表示小于 n 且与 n 互素的正整数的个数。 | 解决同余问题、RSA加密算法、组合数学问题(如欧拉定理)。 |
2. 核心区别
维度 | 线性筛 | 欧拉函数 |
---|---|---|
性质 | 一种算法(工具) | 一种数论函数(数学对象) |
功能 | 筛选素数,或辅助计算数论函数的值。 | 计算与 n 互质的数的个数。 |
时间复杂度 | O(n) | 计算单个 ϕ(n) 的时间复杂度为 O(n),但结合线性筛可优化为 O(n)。 |
输入输出 | 输入一个整数 n,输出所有素数或预处理数论函数的值。 | 输入一个整数 n,输出与 n 互质的数的个数。 |
3. 联系
虽然线性筛和欧拉函数是独立的概念,但线性筛可以高效计算欧拉函数的值。
例如:使用线性筛法预处理欧拉函数 ϕ(n) 的步骤:
-
初始化:对每个数 i,标记 ϕ(i)=i。
-
筛法过程:
-
当筛到素数 p 时,对所有 p 的倍数 i:
-
如果 i 是素数 p 的首次倍数,则 ϕ(i)=ϕ(i/p)⋅p。
-
如果 i 是素数 p 的非首次倍数,则 ϕ(i)=ϕ(i)⋅p。
-
-
4.代码示例
(1) 线性筛法筛选素数
vector<int> linear_sieve(int n) {
vector<int> primes;
vector<bool> is_prime(n + 1, true);
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) primes.push_back(i);
for (int p : primes) {
if (i * p > n) break;
is_prime[i * p] = false;
if (i % p == 0) break; // 关键:确保每个数只被最小素因子筛一次
}
}
return primes;
}
(2) 线性筛法计算欧拉函数
vector<int> euler_phi_linear(int n) {
vector<int> phi(n + 1), primes;
phi[1] = 1;
for (int i = 2; i <= n; ++i) {
if (phi[i] == 0) { // i 是素数
primes.push_back(i);
phi[i] = i - 1; // 素数的欧拉函数值为 i-1
}
for (int p : primes) {
if (i * p > n) break;
if (i % p == 0) {
phi[i * p] = phi[i] * p; // p 是 i 的最小素因子
break;
} else {
phi[i * p] = phi[i] * (p - 1); // p 与 i 互质
}
}
}
return phi;
}
5. 总结
线性筛 | 欧拉函数 |
---|---|
是工具(算法),用于生成素数或辅助计算数论函数。 | 是数学对象,表示与 n 互质的数的个数。 |
时间复杂度为 O(n),高效但需要预处理。 | 单独计算时间复杂度较高,但结合线性筛可优化。 |
核心是筛法的实现逻辑(如标记合数)。 | 核心是数论性质(如互质条件)。 |
关键点:
线性筛是算法,欧拉函数是函数。线性筛可以用于高效计算欧拉函数,但两者本质不同。