Sky's Octopress Blog

为者常成,行者常至

扩展欧几里得算法(Extended Euclidean Algorithm)

| Comments

欧几里得算法几乎算是我们最早接触到的算法,小学生就开始使用了。其实我更偏向于称之为辗转相除法,因为数学在中国的起源真的很早,然而文化背景的原因,这些宝贵的知识一直当作奇技淫巧。今天这里并不是要重复辗转相除法,而是讲它的一个有趣的变型:扩展辗转相除法。

重温辗转相除法(Eculdiean algorithm)的过程

: 求 $888$ 和 $54$ 的最大公约数 $gcd(888,54)$ 。

倒数第二步 $(2)$ 的余数就是最后的结果,即 $gcd(888,54) = 6$

扩展辗转相除法(Extended Eculdiean algorithm)

在求解上例的过程中,我们总可以找到这样一组整数 $(x,y)$ 使得下式1成立。

具体作法:将 $gcd(a,b)$ 的求解过程反过来,每一步等式左边代入前一步,直到第一步。拿上例来说,过程如下:

求得 $(x,y) = (-2, 33)$。到这里,大多数讲扩展辗转相除法的内容就停止了,其实这离真正可以应用和实现还差一步。

我们来看看一般形式,假设我们用了 $n$ 步迭代,应用辗转相除法求解出最大公约数 $gcd(a,b)$,即:

容易发现 $b_{i+1} = a_{i}, c_{i+1} = b_{i}$。 假设最后一步是$b_{0} = 0$,那么 $gcd(a,b)=a_{0}$ 同时,我们可以假设在第 $i$ 步有:

可以通过将 $i+1$ 步的变型($c_{i+1} = b_{i}$)代入 $b_{i}$ :

事实上,$(13)$ 符合 $(11)$ 的形式($i>0$),可以比较系数得出:

对于 $i=0$ 的边界情况,我们可以直接用 $\text{(11)}$ 得出:

需要注意的是 $d_{i} = [a_{i}/b_{i}]$ ,$c_{i} = a_{i} \mod b_{i}$

应用及代码实现(Python)

扩展辗转相除法是求解模反元素(Modular multiplicative inverse)的方法之一,求解模反元素是 RSA 加密算法2的主要步骤之一:

或者表达为:

实现扩展辗转相除法的Python 代码如下:

Comments