扩展欧几里得算法

来自testwiki
跳转到导航 跳转到搜索

Template:NoteTA 扩展欧几里得算法Template:Lang-en)是欧几里得算法(又叫辗转相除法)的扩展。已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,找到整数x、y(其中一个可能是负数),使它们满足貝祖等式ax+by=gcd(a,b)[1]如果a是负数,可以把问题转化成|a|(x)+by=gcd(|a|,b)|a|为a的绝对值),然后令x=(x)

在欧几里得算法中,我们仅利用了每步带余除法所得的余数。扩展欧几里得算法还利用了带余除法所得的商,在辗转相除的同时也能得到貝祖等式[2]中的x、y两个系数。以扩展欧几里得算法求得的系数是满足裴蜀等式的最简系数。

另外,扩展欧几里得算法是一种自验证算法,最后一步得到的si+1ti+1si+1ti+1的含义见下文)乘以gcd(a,b)后恰为ab,可以用来验证计算结果是否正确。

扩展欧几里得算法可以用来计算模逆元,而计算模逆元是RSA加密算法中生成公钥、私钥的必要步骤。

算法和举例

在标准的欧几里得算法中,我们记欲求最大公约数的两个数为a,b,第i步带余除法得到的商为qi,余数为ri+1,则欧几里得算法可以写成如下形式:

r0=ar1=bri+1=ri1qiri0ri+1<|ri|

当某步得到的ri+1=0时,计算结束。上一步得到的ri即为a,b的最大公约数。

扩展欧几里得算法在qiri的基础上增加了两组序列,记作siti,并令s0=1s1=0t0=0t1=1,在欧几里得算法每步计算ri+1=ri1qiri之外额外计算si+1=si1qisiti+1=ti1qiti,亦即:

r0=ar1=bs0=1s1=0t0=0t1=1ri+1=ri1qiri0ri+1<|ri|si+1=si1qisiti+1=ti1qiti

算法结束条件与欧几里得算法一致,也是ri+1=0,此时所得的siti即满足等式gcd(a,b)=ri=asi+bti

下表以a=240b=46为例演示了扩展欧几里得算法。所得的最大公因数是2,所得贝祖等式gcd(240,46)=2=9*240+47*46。同时还有自验证等式|23|*2=46|120|*2=240

序号 i Template:Blue Template:Purple Template:Brown ti
0 Template:Green Template:Brown 0
1 Template:Green Template:Brown 1
2 Template:Green ÷ Template:Green = Template:Blue Template:GreenTemplate:Blue × Template:Green = Template:Purple Template:BrownTemplate:Blue × Template:Brown = Template:Brown 0 − Template:Blue × 1 = −5
3 Template:Green ÷ Template:Purple = Template:Blue Template:GreenTemplate:Blue × Template:Purple = Template:Purple Template:BrownTemplate:Blue × Template:Brown = Template:Brown 1 − Template:Blue × −5 = 21
4 Template:Purple ÷ Template:Purple = Template:Blue Template:PurpleTemplate:Blue × Template:Purple = Template:Purple Template:BrownTemplate:Blue × Template:Brown = Template:Brown −5 − Template:Blue × 21 = −26
5 Template:Purple ÷ Template:Purple = Template:Blue Template:PurpleTemplate:Blue × Template:Purple = Template:Red Template:BrownTemplate:Blue × Template:Brown = Template:Orange 21 − Template:Blue × −26 = Template:Orange
6 Template:Purple ÷ Template:Purple = Template:Blue Template:PurpleTemplate:Blue × Template:Purple = Template:Red Template:BrownTemplate:Blue × Template:Brown = Template:Orange −26 − Template:Blue × 47 = Template:Orange

這個過程也可以用初等變換表示。

(240461001)(10461051)(10614521)(46542621)(42592647)[3]

得到9×240+47×46=2

证明

由于0ri+1<|ri|ri序列是一个递减序列,所以本算法可以在有限步内终止。又因为ri+1=ri1riqi(ri1,ri)(ri,ri+1)的最大公约数是一样的,所以最终得到的rkab的最大公约数。

在欧几里得算法正确性的基础上,又对于a=r0b=r1有等式asi+bti=ri成立(i = 0 或 1)。这一关系由下列递推式对所有i>1成立:

ri+1=ri1riqi=(asi1+bti1)(asi+bti)qi=(asi1asiqi)+(bti1btiqi)=asi+1+bti+1

因此siti满足裴蜀等式,这就证明了扩展欧几里得算法的正确性。

实现

以下是扩展欧几里德算法的Python实现:

def ext_euclid(a, b):
    old_s, s = 1, 0
    old_t, t = 0, 1
    old_r, r = a, b
    if b == 0:
        return 1, 0, a
    else:
        while(r!=0):
            q = old_r // r
            old_r, r = r, old_r-q*r
            old_s, s = s, old_s-q*s
            old_t, t = t, old_t-q*t
    return old_s, old_t, old_r

扩展欧几里得算法C++实现:

#include <bits/stdc++.h>
using namespace std;

int ext_euc(int a, int b, int &x, int &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return a;
    }

    int d = ext_euc(b, a % b, y, x);
    y -= a / b * x;

    return d;
}

int main()
{
    int a, b, x, y;
    cin >> a >> b;

    ext_euc(a, b, x, y);
    cout << x << ' ' << y << endl;
    return 0;
}

参考资料

Template:Reflist

參考文獻

外部連結

Template:数论算法