扩展欧几里得算法又称碾转相除法或者欧几里得算法,用于计算两个正整数a,b的最大公约数。
理解欧几里得算法,首先看一个定义:a和b的最大公约数g是a和b的线性和中(绝对值)最小的一个,即所有形如xa + yb(其中x和y是整数)的数中(绝对值)最小的数。
计算过程
辗转相除法是一种递归 算法,每一步计算的输出值就是下一步计算时的输入值。 设 k 表示步骤数(从0开始计数),算法的计算过程如下。每一步的输入是都是前两次计算的余数rk−1和rk−2。因为每一步计算出的余数都在不断减小,所以,rk−1小于rk−2。在第k步中,算法计算出满足以下等式的商qk和余数rk:
- r k−2 = q k r k−1 + r k
其中rk < rk−1。也就是rk−2要不断减去rk−1直到比rk−1小。
在第一步计算时(k = 0),设r−2和r−1分别等于a和b,第2步(此时k = 1)时计算r−1(即b)和r0(第一步计算产生的余数)相除产生的商和余数,以此类推。整个算法可以用如下等式表示:
- a = q 0 b + r 0
- b = q 1 r 0 + r 1
- r 0 = q 2 r 1 + r 2
- r 1 = q 3 r 2 + r 3
- …
如果输入参因为a < b,所以a和b相除得到的商q0等于0,余数r0等于a。所以在运算的每一步中得出的余数一定小于上一步计算的余数(rk一定小于rk−1)。
由于每一步的余数都在减小并且不为负数,必然存在第N步时rN等于0,使算法终止,rN−1 就是a和b的最大公约数。其中N不可能无穷大,因为在r0和0之间只有有限个自然数。
证明
辗转相除法的正确性可以用两步来证明。首先,算法的最终结果rN−1同时整除a和b。因为它是一个公约数,所以必然小于或者等于最大公约数g。然后,任何a和b的公约数都能整除rN−1。所以g一定小于或等于rN−1。两个不等式只在rN−1 = g是同时成立。具体证明如下:
- 证明rN−1同时整除a和b:
-
因为余数
r
N是0,
r
N−1能够整除
r
N−2:
- r N−2 = q N r N−1
-
因为
r
N−1能够整除
r
N−2,所以也能够整除
r
N−3:
- r N−3 = q N−1 r N−2 + r N−1
- 同理可证 r N−1可以整除所有之前步骤的余数,包括 a和 b,即 r N−1是 a和 b的公约数, r N−1 ≤ g。
-
因为余数
r
N是0,
r
N−1能够整除
r
N−2:
- 证明任何整除a和b的自然数g(也就是a和b的公约数)都能整除rN-1:
- 根据定义, a和 b可以写成 g的倍数: a = mg、 b = ng,其中 m和 n是自然数。因为 r 0 = a − q 0 b = mg − q 0 ng = ( m − q 0 n) g,所以 g整除 r 0。同理可证 g整除每个余数 r 1、 r 2…… r N-1。所以,最大公约数 g一定整除 r N−1,因而 g ≤ r N−1。
因为第一步的证明告诉我们rN−1 ≤ g,所以g = rN−1。即:
-
用类似辗转相除法,求二元一次不定方程47x+30y=1的整数解。
47=30*1+17
30=17*1+13
17=13*1+4
13=4*3+1
然后把它们改写成“余数等于”的形式
17=47*1+30*(-1) //式1
13=30*1+17*(-1) //式2
4=17*1+13*(-1) //式3
1=13*1+4*(-3)
然后把它们“倒回去”
1=13*1+4*(-3) //应用式3
1=13*1+[17*1+13*(-1)]*(-3)
1=13*4+17*(-3) //应用式2
1=[30*1+17*(-1)]*4+17*(-3)
1=30*4+17*(-7) //应用式1
1=30*4+[47*1+30*(-1)]*(-7)
1=30*11+47*(-7)
得解x=-7, y=11。
这个方法就是扩展欧几里德算法。
g = GCD(a, b) = GCD(b, r0) = GCD(r0, r1) = … = GCD(rN−2, rN−1) = rN−1
例子
JAVA实现
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}