|
|
1. 扩展欧几里得算法
扩展欧几里得算法是求解模方程的基础,它不仅能计算两个数的最大公约数,还能找到满足方程 ax + by = gcd(a, b) 的整数解 x 和 y。这个算法是递归实现的,通过回溯计算出最终的解。
2. 一元线性同余方程
一元线性同余方程的形式为 ax ≡ b (mod m),求解该方程的步骤:
使用扩展欧几里得算法计算 gcd(a, m)
若 b 不能被 gcd(a, m) 整除,则方程无解
否则,先求出一个特解,再根据 gcd(a, m) 的值确定解的数量和通解形式
示例 1 中,方程 3x ≡ 6 (mod 9) 的解为 x ≡ 2, 5, 8 (mod 9),共 3 个解,因为 gcd(3, 9) = 3。
3. 中国剩余定理
中国剩余定理用于求解模数两两互质的同余方程组,形式为:
plaintext
x ≡ a₁ (mod m₁)
x ≡ a₂ (mod m₂)
...
x ≡ aₙ (mod mₙ)
其中所有 mᵢ 两两互质。求解过程是逐步合并方程,最终得到一个解 x ≡ c (mod M),其中 M 是所有 mᵢ 的乘积。
示例 2 中,方程组的解为 x ≡ 23 (mod 105),因为 105 是 3、5、7 的乘积,且 23 满足所有三个同余式。
4. 模数不互质的同余方程组
当模数不互质时,不能直接应用中国剩余定理,需要更一般的解法:
逐步合并两个方程,检查是否有解
若有解,则得到一个新的同余方程
重复此过程直到所有方程合并完成
示例 3 中,方程组 x ≡ 2 (mod 4) 和 x ≡ 4 (mod 6) 的解为 x ≡ 10 (mod 12),因为 10 同时满足两个同余式。
这些算法在密码学、数论和计算机科学中有广泛应用,例如在 RSA 加密、哈希函数设计和伪随机数生成等领域。
[C++] 纯文本查看 复制代码 #include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;
/**
* 扩展欧几里得算法
* 求解 ax + by = gcd(a, b)
* @param a 方程系数
* @param b 方程系数
* @param x 解x的引用
* @param y 解y的引用
* @return a和b的最大公约数
*/
long long extendedGcd(long long a, long long b, long long& x, long long& y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
long long x1, y1;
long long g = extendedGcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return g;
}
/**
* 求解一元线性同余方程 ax ≡ b (mod m)
* 方程有解的充要条件是 gcd(a, m) 能整除 b
* @param a 系数
* @param b 常数项
* @param m 模数
* @param x 解的引用(若有解)
* @return 解的数量,0表示无解,否则返回解的数量(gcd(a,m))
*/
int solveLinearCongruence(long long a, long long b, long long m, long long& x) {
long long g, x0, y0;
g = extendedGcd(a, m, x0, y0); // 求解 ax0 + my0 = g
// 检查是否有解:b必须能被g整除
if (b % g != 0) {
return 0; // 无解
}
// 计算一个特解
x0 = x0 * (b / g) % m;
// 保证解为正数
if (x0 < 0) {
x0 += m;
}
x = x0;
// 解的数量为g,通解为 x0 + k*(m/g),其中k=0,1,...,g-1
return g;
}
/**
* 中国剩余定理(求解同余方程组)
* 解形如:
* x ≡ a1 (mod m1)
* x ≡ a2 (mod m2)
* ...
* x ≡ an (mod mn)
* 要求所有mi两两互质
* @param congruences 同余式列表,每个元素为(a_i, m_i)
* @param x 解的引用
* @param mod 解的模数(所有m_i的乘积)
* @return 是否有解
*/
bool chineseRemainderTheorem(const vector<pair<long long, long long>>& congruences,
long long& x, long long& mod) {
x = 0;
mod = 1;
for (const auto& [a, m] : congruences) {
// 当前方程:x ≡ a (mod m)
// 合并方程:x = x0 + k*mod,代入得 x0 + k*mod ≡ a (mod m)
// 即 k*mod ≡ (a - x0) (mod m)
long long g, k, tmp;
long long c = (a - x) % m;
if (c < 0) c += m; // 确保c为正数
g = extendedGcd(mod, m, k, tmp); // 求解 k*mod + tmp*m = g
// 检查是否有解
if (c % g != 0) {
return false; // 无解
}
// 计算k的一个解
long long lcm = mod / g * m; // 最小公倍数
k = k * (c / g) % (m / g);
if (k < 0) k += m / g;
// 更新x和mod
x += k * mod;
mod = lcm;
x %= mod; // 保持x在[0, mod)范围内
}
return true;
}
/**
* 求解模数不互质的同余方程组
* @param congruences 同余式列表,每个元素为(a_i, m_i)
* @param x 解的引用
* @param mod 解的模数(所有m_i的最小公倍数的因子)
* @return 是否有解
*/
bool solveCongruenceSystem(const vector<pair<long long, long long>>& congruences,
long long& x, long long& mod) {
x = 0;
mod = 1;
for (const auto& [a, m] : congruences) {
// 合并方程:x ≡ x0 (mod mod) 和 x ≡ a (mod m)
long long g, tmp, k;
long long c = (a - x) % m;
if (c < 0) c += m;
g = extendedGcd(mod, m, k, tmp);
// 检查是否有解
if (c % g != 0) {
return false;
}
// 计算新的解和模数
long long new_mod = mod / g * m;
k = k * (c / g) % (m / g);
if (k < 0) k += m / g;
x += k * mod;
mod = new_mod;
x %= mod;
}
return true;
}
int main() {
// 示例1:求解一元线性同余方程
cout << "=== 示例1:一元线性同余方程 ===" << endl;
long long a = 3, b = 6, m = 9;
long long x;
int solutions = solveLinearCongruence(a, b, m, x);
cout << "求解方程: " << a << "x ≡ " << b << " (mod " << m << ")" << endl;
if (solutions == 0) {
cout << "方程无解" << endl;
} else {
cout << "方程有 " << solutions << " 个解" << endl;
long long step = m / solutions;
for (int i = 0; i < solutions; ++i) {
long long sol = (x + i * step) % m;
cout << "解 " << i + 1 << ": x ≡ " << sol << " (mod " << m << ")" << endl;
}
}
cout << endl;
// 示例2:中国剩余定理(模数互质)
cout << "=== 示例2:中国剩余定理(模数互质) ===" << endl;
vector<pair<long long, long long>> crt_congs = {
{2, 3}, // x ≡ 2 (mod 3)
{3, 5}, // x ≡ 3 (mod 5)
{2, 7} // x ≡ 2 (mod 7)
};
long long crt_x, crt_mod;
bool crt_has_solution = chineseRemainderTheorem(crt_congs, crt_x, crt_mod);
if (crt_has_solution) {
cout << "方程组的解为: x ≡ " << crt_x << " (mod " << crt_mod << ")" << endl;
// 验证解
for (const auto& [a, m] : crt_congs) {
cout << "验证: " << crt_x << " mod " << m << " = " << crt_x % m << " (应等于 " << a << ")" << endl;
}
} else {
cout << "方程组无解" << endl;
}
cout << endl;
// 示例3:求解模数不互质的同余方程组
cout << "=== 示例3:模数不互质的同余方程组 ===" << endl;
vector<pair<long long, long long>> sys_congs = {
{2, 4}, // x ≡ 2 (mod 4)
{4, 6} // x ≡ 4 (mod 6)
};
long long sys_x, sys_mod;
bool sys_has_solution = solveCongruenceSystem(sys_congs, sys_x, sys_mod);
if (sys_has_solution) {
cout << "方程组的解为: x ≡ " << sys_x << " (mod " << sys_mod << ")" << endl;
// 验证解
for (const auto& [a, m] : sys_congs) {
cout << "验证: " << sys_x << " mod " << m << " = " << sys_x % m << " (应等于 " << a << ")" << endl;
}
} else {
cout << "方程组无解" << endl;
}
return 0;
}
|
|