首页 > 代码库 > 如何使用循环而不是递归反推的方式实现拓展欧几里德算法

如何使用循环而不是递归反推的方式实现拓展欧几里德算法

平常我们使用拓展欧几里德算法求pm + qn = gcd(m, n)这种表示时,一般都会选择递归的方式来实现,因为欧几里得算法的递归深度最多也只有O(lgn), according to lame‘s theorem,所以这个递归用栈是可以忽略的。

但其实只需要循环就可以求出一组pm + qn = gcd(m, n)的表示,将栈深度保持在O(1),这样的写法在使用函数调用的高级语言中看起来复杂一点但在汇编编程时就显得比较简单。

方法是假设第k次迭代中的两个数分别为 M(k) 和 N(k),我们始终维持住一个循环不变式F

F: xm + yn = M(k) 以及 x‘m + y‘n = N(k)。

那么在第0步时, M(0) = m, N(0) = n,显然只需要取x = 1, y = 0, x‘ = 0, y‘ = 1即可

归纳:假设第k步运算时,x*m + y*n = M(k), x‘m + y‘n = N(k)

而M(k+1) = N(k), 可以直接利用newX = x‘, newY = y‘得到newX*m + newY*n = M(k + 1)

而N(k+1) = M(k) MOD N(k) = M(k) - [M(k)/N(k)]*N(k),我们只需要利用x*m + y*n = M(k) 减去 x‘m + y‘n = N(K) 左右同乘[M(k)/N(k)]这种小学2年级学的一元二次方程求解(到了大学的线性代数似乎叫高斯消元)的方式得到一个newX‘m + newY‘n = N(k+1),此处运算省略。

再依次用x = newX, y = newY, x‘ = newX‘, y‘ = newY‘替换一下即可保持住这个循环不变式。

最后在算法的结束部分,xm + yn = r, x‘m + yn‘ = 0

输出这个xm + yn = r即是我们要的结果

如何使用循环而不是递归反推的方式实现拓展欧几里德算法