在数论和密码学中,欧几里得算法(Euclidean Algorithm)是一个古老而重要的算法,用于计算两个整数的最大公约数(GCD)。
欧几里得算法(更相减损法)
欧几里得算法基于以下原理:两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。用数学公式表示为:
当余数为0时,此时的除数就是最大公约数。
- 用较大数除以较小数,得到余数
- 用较小数除以余数,再次得到新的余数
- 重复这个过程,直到余数为0
- 此时的除数就是最大公约数
// 递归实现
int gcd_recursive(int a, int b) {if (b == 0) return a;return gcd_recursive(b, a % b);
}// 迭代实现
int gcd_iterative(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;
}
中国古代的更相减损术是中国古代数学著作《九章算术》中记载的一种求最大公约数的方法,成书于东汉时期(约公元1世纪)。《九章算术》的"方田"章中记载:
"约分术曰:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。"
更相减损术的核心思想是:两个数的最大公约数等于较小数与两数差的最大公约数。用现代数学符号表示为:
当两数相等时,这个相等的数就是最大公约数。减法实际上可以替换为除法取余(减到不能再减),这样就接近现代使用的欧几里得算法了。
欧几里得算法的时间复杂度
其时间复杂度为 \(O(\log(\min(a, b)))\)。
可以使用数学知识证明(有难度),欧几里得算法在计算 \(\gcd(a, b)\) 时,最多执行 \(2 \cdot \lfloor \log_2 b \rfloor + 1\) 次除法操作(最坏情况为当输入为连续的斐波那契数时)。平均除法的次数是 \(\frac{12 \ln 2}{\pi^2} \ln n \approx 0.843 \ln n\)。
扩展欧几里得算法
扩展欧几里得算法不仅计算 \(\gcd(a, b)\),还找到整数 \(x\) 和 \(y\),使得满足贝祖等式:
即让 \(a\) 和 \(b\) "拼出" 其最大公约数。
在欧几里得算法的每一步中,我们有:
- \(a = bq + r\),其中 \(q\) 是商,\(r\) 是余数
- \(\gcd(a, b) = \gcd(b, r)\)
我们可以将余数 \(r\) 表示为:
- \(r = a - bq\)
在递归的返回过程中,我们利用这个关系来构造 \(x\) 和 \(y\)。
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 \equiv b \pmod{m}\) 的线性同余方程(也包括求解乘法逆元)。