欧几里得算法(Euclidean Algorithm)是一种高效计算两个非负整数最大公约数(GCD)的方法。它不仅简单易懂,而且在数学和计算机科学中有着广泛的应用。以下是对该算法的深入讲解,包括其原理、扩展、时间复杂度分析以及实际应用。
欧几里得算法的核心思想基于以下数学原理:
数学证明:
设 d = gcd ( a , b ) d = \gcd(a, b) d=gcd(a,b),则 d 能整除 a 和 b。根据除法的定义:
a = b ⋅ q + r a = b \cdot q + r a=b⋅q+r
其中 q 是商, r = a m o d b r = a \mod b r=amodb 是余数。由于 d 能整除 a 和 b,它也能整除 r。因此, gcd ( a , b ) = gcd ( b , r ) \gcd(a, b) = \gcd(b, r) gcd(a,b)=gcd(b,r)。
其中 q 是商, r = a m o d b r = a \mod b r=amodb 是余数。由于 d 能整除 a 和 b,它也能整除 r。因此, gcd ( a , b ) = gcd ( b , r ) \gcd(a, b) = \gcd(b, r) gcd(a,b)=gcd(b,r)。
通过反复应用这一性质,余数 r 会逐渐减小,最终变为 0,此时算法终止。
示例:
计算 gcd ( 48 , 18 ) \gcd(48, 18) gcd(48,18):
扩展欧几里得算法不仅计算 gcd ( a , b ) \gcd(a, b) gcd(a,b),还能找到满足以下等式的整数 x 和 y:
a ⋅ x + b ⋅ y = gcd ( a , b ) a \cdot x + b \cdot y = \gcd(a, b) a⋅x+b⋅y=gcd(a,b)
这在求解线性同余方程和模反元素时非常有用。
这在求解线性同余方程和模反元素时非常有用。
算法步骤:
示例:
求解 48 x + 18 y = gcd ( 48 , 18 ) 48x + 18y = \gcd(48, 18) 48x+18y=gcd(48,18):
欧几里得算法的时间复杂度为 O ( log min ( a , b ) ) O(\log \min(a, b)) O(logmin(a,b))。这是因为每次迭代中,余数 r 至少减小为原来的一半:
因此,算法的迭代次数最多为 O ( log min ( a , b ) ) O(\log \min(a, b)) O(logmin(a,b))。
用于计算两个整数的最大公约数(GCD)。
#include
using namespace std;
// 欧几里得算法
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int a = 48, b = 18;
cout << "GCD of " << a << " and " << b << " is: " << gcd(a, b) << endl;
return 0;
}
输出:
GCD of 48 and 18 is: 6
用于计算最大公约数,并找到满足 (ax + by = \gcd(a, b)) 的整数 (x) 和 (y)。
#include
using namespace std;
// 扩展欧几里得算法
int extended_gcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1;
int gcd = extended_gcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return gcd;
}
int main() {
int a = 48, b = 18;
int x, y;
int gcd_value = extended_gcd(a, b, x, y);
cout << "GCD of " << a << " and " << b << " is: " << gcd_value << endl;
cout << "Coefficients (x, y) are: (" << x << ", " << y << ")" << endl;
cout << "Equation: " << a << "*" << x << " + " << b << "*" << y << " = " << gcd_value << endl;
return 0;
}
输出:
GCD of 48 and 18 is: 6
Coefficients (x, y) are: (-1, 3)
Equation: 48*-1 + 18*3 = 6
扩展欧几里得算法可以用于求解形如 (ax \equiv b \pmod{m}) 的线性同余方程。
#include
using namespace std;
// 扩展欧几里得算法
int extended_gcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1;
int gcd = extended_gcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return gcd;
}
// 求解线性同余方程 ax ≡ b (mod m)
bool solve_linear_congruence(int a, int b, int m, int &x) {
int x0, y0;
int gcd_value = extended_gcd(a, m, x0, y0);
// 如果 b 不能被 gcd(a, m) 整除,则无解
if (b % gcd_value != 0) {
return false;
}
// 计算特解
x = x0 * (b / gcd_value) % m;
if (x < 0) {
x += m; // 保证解为非负数
}
return true;
}
int main() {
int a = 35, b = 10, m = 50;
int x;
if (solve_linear_congruence(a, b, m, x)) {
cout << "Solution to " << a << "x ≡ " << b << " (mod " << m << ") is: x = " << x << endl;
} else {
cout << "No solution exists for " << a << "x ≡ " << b << " (mod " << m << ")" << endl;
}
return 0;
}
输出:
Solution to 35x ≡ 10 (mod 50) is: x = 14
扩展欧几里得算法可以用于计算模反元素,即找到满足 a ⋅ x ≡ 1 ( m o d m ) a \cdot x \equiv 1 \pmod{m} a⋅x≡1(modm) 的 x。
#include
using namespace std;
// 扩展欧几里得算法
int extended_gcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1;
int gcd = extended_gcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return gcd;
}
// 计算模反元素
int mod_inverse(int a, int m) {
int x, y;
int gcd_value = extended_gcd(a, m, x, y);
// 如果 a 和 m 不互质,则模反元素不存在
if (gcd_value != 1) {
return -1; // 表示无解
}
// 保证结果为非负数
x = (x % m + m) % m;
return x;
}
int main() {
int a = 3, m = 11;
int inverse = mod_inverse(a, m);
if (inverse == -1) {
cout << "Modular inverse of " << a << " mod " << m << " does not exist." << endl;
} else {
cout << "Modular inverse of " << a << " mod " << m << " is: " << inverse << endl;
}
return 0;
}
输出:
Modular inverse of 3 mod 11 is: 4
欧几里得算法是一种高效、经典的算法,其核心思想是通过辗转相除法逐步减小问题规模。它不仅用于计算最大公约数,还可以扩展到求解线性同余方程和模反元素,在数论、密码学和计算机科学中有着广泛的应用。其时间复杂度为 O ( log min ( a , b ) ) O(\log \min(a, b)) O(logmin(a,b)),是一种非常高效的算法。