C++数论
一、数论核心概念与算法
1. 整除与素数
整除:整数 \(a\) 整除 \(b\)(记作 \(a|b\))当且仅当 \(b = ka\)(\(k \in \mathbb{Z}\))。
素数:只能被 1 和自身整除的大于 1 的自然数。
素数判定:
- 朴素法:检查 \(2 \sim \sqrt{n}\) 是否有因数。
- 优化:只需检查 \(2 \sim \sqrt{n}\) 内的素数是否为因数(结合素数筛法)。
代码示例(C++):
// 判断素数(优化版)
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return false;
}
return true;
}
2. 最大公约数(GCD)与最小公倍数(LCM)
- GCD 算法:欧几里得算法(递归实现)
- LCM 公式:\(LCM(a, b) = \frac{|a \cdot b|}{GCD(a, b)}\)
- 代码示例:
3. 扩展欧几里得算法
用于求解线性同余方程 \(ax + by = \gcd(a, b)\) 的整数解 \((x, y)\)。
代码示例(C++):
void extendedGCD(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1; y = 0;
return;
}
int x1, y1;
extendedGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
}
4. 中国剩余定理(CRT)
解决形如 \(x \equiv a_i \pmod {m_i}\) 的同余方程组。
核心思想:通过构造乘积和逆元逐步合并解。
应用场景:时间同步、模块化计算等。
5. 费马小定理与快速幂
- 费马小定理:若 \(p\) 为素数且 \(a\) 不整除 \(p\),则 \(a^{p-1} \equiv 1 \pmod p\)。
- 快速幂算法:高效计算 \(a^b \bmod m\),时间复杂度 \(O(\log b)\)。
代码示例(C++):
int fastPower(int a, int b, int mod) {
int res = 1;
while (b > 0) {
if (b & 1) res = (res * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return res;
}
二、排列组合与概率
1. 排列与组合
- 排列(有序选择):\(P(n, m) = \frac{n!}{(n-m)!}\)
- 组合(无序选择):\(C(n, m) = \frac{n!}{m!(n-m)!}\)
- 代码示例(C++):
2. 容斥原理
用于计算满足多个条件的集合元素个数。
公式:\(|A_1 \cup A_2 \cup \cdots \cup A_n| = \sum |A_i| - \sum |A_i \cap A_j| + \sum |A_i \cap A_j \cap A_k| - \cdots\)
应用场景:统计问题、集合计数。
3. 鸽巢原理(抽屉原理)
若 \(n\) 个物品放入 \(m\) 个抽屉(\(n > m\)),则至少有一个抽屉包含超过 1 个物品。
扩展应用:证明存在性问题,如哈希冲突、生日悖论等。
三、数论算法实战应用
1. 组合生成与排列生成
- 递归回溯法生成所有组合/排列。
- 优化:迭代生成(如字典序排列)。
示例:生成 \(n\) 个元素中 \(m\) 个元素的组合。
2. 质因数分解
- 试除法分解质因数。
- Pollard-Rho 算法(分解大数)。
代码示例(C++):
// 试除法分解质因数
map<int, int> factorize(int n) {
map<int, int> factors;
for (int i = 2; i * i <= n; ++i) {
while (n % i == 0) {
factors[i]++;
n /= i;
}
}
if (n > 1) factors[n]++;
return factors;
}
3. 密码学应用:RSA 算法
- 密钥生成:选择大素数 \(p, q\),计算 \(n = pq\),\(e\) 与 \(\phi(n) = (p-1)(q-1)\) 互素,求 \(d\) 使 \(ed \equiv 1 \pmod {\phi(n)}\)。
- 加密:\(c = m^e \bmod n\);解密:\(m = c^d \bmod n\)。
4. 模线性方程求解
- 求解 \(ax \equiv b \pmod m\):使用扩展欧几里得算法。
- 模逆元:求 \(a^{-1} \bmod m\)(当 \(a\) 与 \(m\) 互素时存在)。
四、高级技巧与优化
1. 素数筛法
- 埃拉托斯特尼筛法:\(O(n \log \log n)\) 求 \(n\) 内素数。
- 线性筛法(欧拉筛):\(O(n)\) 高效筛法,避免重复标记。
代码示例(C++):
// 欧拉筛法
vector<bool> isPrime(n + 1, true);
vector<int> primes;
for (int i = 2; i <= n; ++i) {
if (isPrime[i]) primes.push_back(i);
for (int j = 0; j < primes.size() && i * primes[j] <= n; ++j) {
isPrime[i * primes[j]] = false;
if (i % primes[j] == 0) break; // 关键优化
}
}
2. 数论函数
- 欧拉函数 \(\phi(n)\):小于 \(n\) 且与 \(n\) 互素的数的个数。
- 莫比乌斯函数 \(\mu(n)\):用于数论求和的变换。
- 积性函数:研究函数性质与乘积的关系。
3. 高精度计算
- 使用
__int128或自定义大数类处理超大数运算。(参考我的文章《C++高精模版》) - 优化技巧:Karatsuba 算法(快速乘法)、Montgomery 算法(模乘加速)。
五、实战案例
1. 求解线性同余方程组
// 中国剩余定理(CRT)求解
vector<pair<int, int>> equations; // {(a1, m1), (a2, m2),...}
int M = accumulate(equations.begin(), equations.end(), 1, [](int x, auto p) { return x * p.second; });
int ans = 0;
for (auto [a, m] : equations) {
int Mi = M / m;
int inv = extendedGCD(Mi, m, x, y);
ans = (ans + a * Mi * inv) % M;
}
cout << ans << endl;
2. 组合数学问题
- 例题:从 \(n\) 个不同元素中选 \(m\) 个的组合数,模 \(10^9+7\)。
- 解法:预处理阶乘及逆元,使用组合公式计算。
六、总结
数论是编程中不可或缺的工具,从基础算法到高级应用,它为密码学、组合优化、高效计算等领域提供了核心支撑。C++ 的高效特性使其成为实现数论算法的理想选择。掌握这些知识,可以解决从简单数学问题到复杂工程场景中的挑战。
参考资料:

浙公网安备 33010602011771号