在上一篇文章中,我们已经熟知了有关公约数和欧几里得算法的相关事宜。详情参见:欧几里得算法求最大公约数。本文将作为上篇文章内容的一个延续,简要阐述拓展欧几里得算法和中国剩余定理。
拓展欧几里得算法
拓展欧几里得算法(Extended Euclidian Algorithm),是欧几里得算法的扩展版本,用于在计算两个数的最大公约数 gcd ( a , b ) \gcd(a, b) gcd(a,b) 的同时,找到这两个整数的 贝祖系数(即这两个整数的线性组合等于其最大公约数的系数)。
举例而言,如果给定两个整数 a , b a, b a,b,我们不仅可以找到这两个整数的最大公约数,还可以找到两个整数 x , y x, y x,y,满足:
a x + b y = gcd ( a , b ) ax + by = \gcd(a, b) ax+by=gcd(a,b)
与此同时,我们也将这个方程称之为 贝祖等式(Bézout’s identity)。拓展欧几里得算法在数论和计算机应用方面有着极其突出的贡献和广泛的应用。例如求解线性同余方程,本文也将会围绕求解同余方程来展开。
线性同余方程
线性同余方程指的是形如 a x ≡ b ( m o d m ) ax \equiv b \pmod m ax≡b(modm) 的方程,其中 a a a 和 b b b 表示两个已知的整数常量, x x x 是需要求解的未知整数,符号 ≡ \equiv ≡ 表示同余关系,即等式两边同时对 m m m 取模结果相同。
具体地说,线性同余方程要求找到一个整数 x x x,使得 a x ax ax 除以 m m m 所得的余数等于 b b b,或者说 a x ax ax 与 b b b 对 m m m 取余后余数相等。该类型的问题通常存在唯一的解或者无解。
拓展欧几里得算法过程推导
拓展欧几里得算法与普通的欧几里得算法相同,都可以通过递归的方式来非常简便地计算出结果。
假设有两个非负整数 a a a 和 b b b(在满足 a ≤ b a \le b a≤b 的情况下),设 r = a m o d b r = a \mod b r=amodb,那么根据欧几里得算法可以得出结论 gcd ( a , b ) = gcd ( b , r ) \gcd(a, b) = \gcd(b, r) gcd(a,b)=gcd(b,r)。根据欧几里得算法的推到过程,可以得到:
b x 1 + r y 1 = gcd ( b , r ) bx_1 + ry_1 = \gcd(b, r) bx1+ry1=gcd(b,r)
因为 r = a − ⌊ a b ⌋ b r = a - \left\lfloor\frac{a}{b}\right\rfloor b r=a−⌊ba⌋b,所以代入推出:
gcd ( a , b ) = b x 1 + ( a − ⌊ a b ⌋ b ) y 1 \gcd(a, b) = bx_1 + (a - \left\lfloor\frac{a}{b}\right\rfloor b)y_1 gcd(a,b)=bx1+(a−⌊ba⌋b)y1
经过化简可以得到:
gcd ( a , b ) = a y 1 + b ( x 1 − ⌊ a b ⌋ y 1 ) \gcd(a, b) = ay_1 + b(x_1 - \left\lfloor\frac{a}{b}\right\rfloor y_1) gcd(a,b)=ay1+b(x1−⌊ba⌋y1)
由此可以看出, x = y 1 x = y_1 x=y1 和 y = x 1 − ⌊ a b ⌋ y 1 y = x_1 - \left\lfloor\frac{a}{b}\right\rfloor y_1 y=x1−⌊ba⌋y1 是符合原式的贝祖系数。
拓展欧几里得算法代码
int extended_gcd(int a, int b, int &x, int &y) {
if (a == 0) {
x = 0, y = 1;
return b;
}
int x1, y1;
int gcd = extended_gcd(b % a, a, x1, y1);
x = y1 - (b / a) * x1;
y = x1;
return gcd;
}
参考上述代码,extended_gcd
函数接受两个整数
a
a
a 和
b
,
b,
b,并计算它们的最大公约数,并通过引用参数
x
x
x 和
y
y
y 返回贝祖系数。
中国剩余定理背景
谈到了求解同余方程,那就不得不提 中国剩余定理(Chinese Remainder Theorem)。中国剩余定理又称“孙子定理”,最早可见于中国南北朝时期(公元5世纪)的数学著作《孙子算经》卷下第二十六题,叫做 “物不知数” 问题,原文如下(百度百科提供):
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?即,一个整数除以三余二,除以五余三,除以七余二,求这个整数。《孙子算经》中首次提到了同余方程组问题,以及以上具体问题的解法,因此在中文数学文献中也会将中国剩余定理称为孙子定理。
中国剩余定理提供了一种在模数互素的情况下解决一组同余方程组的方法,而拓展欧几里得算法可以用来计算模数不互素的情况下的解。
中国剩余定理算法与推导
在中国剩余定理中,假设有一个同余方程组:
{ x ≡ a 1 ( m o d m ) 1 x ≡ a 2 ( m o d m ) 2 ⋮ x ≡ a n ( m o d m ) n \begin{cases} x \equiv a_1 \pmod m_1\\ x \equiv a_2\pmod m_2\\ \vdots\\ x \equiv a_n\pmod m_n \end{cases} ⎩ ⎨ ⎧x≡a1(modm)1x≡a2(modm)2⋮x≡an(modm)n
其中, m 1 , m 2 , ⋯ , m n m_1, m_2, \cdots, m_n m1,m2,⋯,mn 两两互质。中国剩余定理告诉我们,以上方程存在唯一的一个解 x x x,模数为 m 1 , m 2 , ⋯ , m n m_1, m_2, \cdots, m_n m1,m2,⋯,mn。
当模数不互素时,我们可以使用拓展欧几里得算法来辅助求解。具体步骤如下:
- 计算 M = m 1 ⋅ m 2 , ⋯ , m n M = m_1 \cdot m_2, \cdots, m_n M=m1⋅m2,⋯,mn。
- 对于每一个 i i i,计算 M i = M m i M_i = \frac{M}{m_i} Mi=miM。
- 对于每个 i i i,使用拓展欧几里得算法计算 M i M_i Mi 在模 m i m_i mi 下的逆元 t i t_i ti。
- 最后的解 x x x 可以通过如下公式计算: x = ∑ i = 1 n a i M i t i m o d M x = \sum_{i=1}^{n} a_i M_i t_i \mod M x=∑i=1naiMitimodM。
中国剩余定理代码示例
int chinese_remainder_theorem(const vector<int> &a, const vector<int> &m) {
int M = 1;
for (int mi : m) {
M *= mi;
}
int result = 0;
for (size_t i = 0; i < a.size(); ++i) {
int ai = a[i];
int mi = m[i];
int Mi = M / mi;
int xi, yi;
extended_gcd(Mi, mi, xi, yi);
result = (result + ai * Mi * xi) % M;
}
// 保证结果为正
if (result < 0) {
result += M;
}
return result;
}
其中 a
向量 和 b
向量 分别表示余数数组和模数数组。
相关引用
- GeeksforGeeks. Euclidean Algorithms - Basic and Extended. GeeksforGeeks, https://www.geeksforgeeks.org/euclidean-algorithms-basic-and-extended/, accessed May 22, 2024.
- GeeksforGeeks. Introduction to Chinese Remainder Theorem. GeeksforGeeks, https://www.geeksforgeeks.org/introduction-to-chinese-remainder-theorem/, accessed May 22, 2024.
- cp-algorithms contributors. “Chinese Remainder Theorem.” cp-algorithms, Oct 16, 2023, https://cp-algorithms.com/algebra/chinese-remainder-theorem.html. Accessed May 22, 2024.