扩展欧几里德(辗转相除法求最大公约数)

1. 欧几里德算法求解最大公约数

1.1 算法过程

欧几里德法又名辗转相除法,可以用于求解两个正整数的最大公约数。他认为,两个正整数的最大公约数等于他们二者中较小的数和较大数与叫较小数取余值的公约数,即,假设有两个正整数 a a a b b b,且 a ≥ b a \ge b ab。用 g c d ( a , b ) gcd(a, b) gcd(ab)表示 a a a b b b的最大公约数,则 g c d ( a , b ) = g c d ( b , a % b ) gcd(a, b) = gcd(b, a \% b) gcd(a,b)=gcd(b,a%b) 其中, a % b a \% b a%b 表示 a a a b b b 的余数。

由上述表达式可以发现,欧几里德法将求两个较大值 a a a b b b 的最大公约数的问题转为两个相对较小的值 b b b a a a % b b b 求最大公约数的问题。

a 1 = a , b 1 = b , a 2 = b 1 , b 2 = a 1 % b 1 , ⋯   , a n = b n − 1 , b n = a n − 1 % b n − 1 a_{1}=a,b_{1}=b,a_{2}=b_{1},b_{2}=a_{1} \% b_{1},\cdots ,a_{n}=b_{n-1},b_{n}=a_{n-1} \% b_{n-1} a1=a,b1=b,a2=b1,b2=a1%b1,,an=bn1,bn=an1%bn1
a 1 和 b 1 a_{1} 和b_{1} a1b1 的最大公约数 g c d ( a 1 , b 1 ) = ⋯ = g c d ( a n , b n ) gcd(a_{1},b_{1}) = \cdots = gcd(a_{n},b_{n}) gcd(a1,b1)==gcd(an,bn)如此递归n次,当传入的两个值中, a n a_{n} an b n b_{n} bn的倍数时,就可以很容易得到, b n b_{n} bn为二者的最大公约数,同时由于最大公约数相等,可以得出, a 1 和 b 1 a_{1}和 b_{1} a1b1 的最大公约数为 b n b_{n} bn

1.2 欧几里德法求解最大公约数证明

证明:假设 c c c a a a b b b 的最大公约数,则 c c c 也一定为 b b b a a a % b b b 的最大公约数。

需要证明1和2:

  1. 证明 c c c b b b a % b a \% b a%b 的公约数。

    c c c a a a b b b 的公约数,则存在正整数 m m m n n n 使得
    a = m ⋅ c , b = n ⋅ c (1.1) a=m\cdot c,b=n\cdot c \tag{1.1} a=mcb=nc(1.1)同时,根据余数的定义,a%b可以表示为 a % b = a − k ⋅ b (1.2) a \% b = a-k\cdot b \tag{1.2} a%b=akb(1.2)其中, k k k表示 a a a 除以 b b b 向下取整的倍数。

    将公式(1.1)代入公式(1.2)可以得到, a % b = c ⋅ ( m + k ⋅ m ) (1.3) a \% b = c \cdot(m+k \cdot m) \tag{1.3} a%b=c(m+km)(1.3)由此得证c 为a % b 约数,同时 b = n ⋅ c b=n \cdot c b=nc,因此得证 c c c b b b a % b a \% b a%b 的公约数。
      

  2. 证明 c c c b b b a a a % b b b 的最大约数。

    我们采用反证法证明,我们假设 b b b a a a % b b b 的存在最大公约数 d d d,且 d > c d > c d>c则存在正整数 x 、 y x、y xy使得 b = x ⋅ d (1.4) b = x\cdot d \tag{1.4} b=xd(1.4) a % b = y ⋅ d (1.5) a \% b=y\cdot d \tag{1.5} a%b=yd(1.5)
    将公式(1.4)(1.5)代入公式(1.2)中, a a a可以通过\tag{1.4} x 、 y 、 d x、y、d xyd表示为 a = d ⋅ ( y + k ⋅ x ) (1.6) a = d \cdot (y + k \cdot x) \tag{1.6} a=d(y+kx)(1.6)根据公式(1.4)(1.6)可以得到, d 为 a 和 b d为a 和 b dab 的约数,且 d > c d > c d>c,而且在最初的假设条件中 c c c a 和 b a和 b ab 的最大公约数,因此与且 d > c d > c d>c 矛盾,所以不存在大于 c c c 的值 d d d b b b a a a % b b b 的存在最大公约数,即 c c c b b b a a a % b b b 的最大约数。

1.3 代码(c语言)

在书写代码过程中,当我们得到 a n 为 b n a_{n}为b_{n} anbn的倍数时,我们会再进行一次辗转相除取余的操作,最后得到 a n + 1 = g c d ( a , b ) , b n + 1 = 0 a_{n+1}=gcd(a,b),b_{n+1}=0 an+1=gcd(a,b),bn+1=0,此时返回a的值即为所求最大公约数

int gcd(int a, int b) {
	if (!b) return a;
	return gcd(b, a % b);
}

ps:a和b的输入顺序不重要,如果a<b,经过一次函数运行后即会被调整。
 

2. 欧几里德算法求解 a ∗ x + b ∗ y = 1 a*x + b*y =1 ax+by=1方程的一组整数解

2.1 算法思想

扩展欧几里德可以用于求解 a ⋅ x + b ⋅ y = 1 a \cdot x + b\cdot y =1 ax+by=1的一组整数解,其中 a 、 b 、 x 、 y a、b、x、y abxy均为整数。

第一部分中介绍了通过欧几里得算法求解最大公约数,他通过将求 a a a b b b 的最大公约数的问题最终转为一个简单的状态,即一个数为另一个数倍数的时候来求解最大公约数,最终返回,这个过程和我们的递归过程类似。

通过欧几里得求解方程的整数解也是类似的,对于该方程,当 a = ± 1 且 b = 0 a= \pm 1且b=0 a=±1b=0的时候,我们就可以很容易得到方程的解,即 x = ∓ 1 , y x= \mp1,y x=1y为任意值。这就是一个简单的状态。

而通过观察方程可以发现,如果 a a a b b b 存在大于1的公约数,则提取后等式右边会变成一个分数,那么方程将无整数解。因此,只有当系数 a a a b b b 互质,即最大公约数为1时方程才会有整数解。对于两个最大公约数为1的数值,恰巧通过欧几里德法可以不断转换,将两个值转化为1和0,即求解该方程的简单的状态。其中1即为通过欧几里德求得a和b的最大公约数。

2.2 算法原理和过程

假设我们需要求解的是方程为公式:
a 1 ⋅ x 1 + b 1 ⋅ y 1 = 1 (2.1) a_{1}\cdot x_{1}+b_{1}\cdot y_{1} = 1 \tag{2.1} a1x1+b1y1=1(2.1)通过欧几里德的规则迭代方程系数,令
a 2 = b 1 , b 2 = a 1 % b 1 = a 1 − k ⋅ b 1 (2.2) a_{2} = b_{1},b_{2} = a_{1} \% b_{1}=a_{1}-k \cdot b_{1} \tag{2.2} a2=b1b2=a1%b1=a1kb1(2.2)可以得到第一个转换后的方程: a 2 ⋅ x 2 + b 2 ⋅ y 2 = 1 (2.3) a_{2}\cdot x_{2}+b_{2}\cdot y_{2} = 1 \tag{2.3} a2x2+b2y2=1(2.3)将公式(2.2)代入公式(2.3),可以得到 a 1 ⋅ y 2 + b 1 ⋅ ( x 2 − k ⋅ x 1 ) = 1 (2.4) a_{1} \cdot y_{2}+b_{1} \cdot (x_{2}-k \cdot x_{1})=1 \tag{2.4} a1y2+b1(x2kx1)=1(2.4)其中, k k k表示 a a a 除以 b b b 向下取整的倍数。

若我们已知转换后的方程(2.3)的解,即已知 x 2 和 y 2 x_{2}和y_{2} x2y2的值,对比公式(2.1)和公式(2.4)可以发现,原 方程的解可以由 x 2 y 2 x_{2} y_{2} x2y2通过如下运算得到: x 1 = y 2 , y 1 = x 2 − k ⋅ y 2 (2.5) x_{1} = y_{2},y1=x_{2}-k \cdot y_{2} \tag{2.5} x1=y2y1=x2ky2(2.5)
以上过程中,我们通过对方程系数进行转变,得到一个新的方程,同时通过新方程的解,又可以推算出原方程的解。

因此我们通过不断重复以上过程,可以将方程系数转变到一个简单的转态,即 a n = 1 , b n = 0 a_{n}=1,b_{n} = 0 an=1bn=0的时候,此时可以获得第n次转换后的方程的解为,即 x n = 1 , y x_{n}= 1,y xn=1y为任意值,我们可以令 y = 0 y=0 y=0,并以此为基础不断返回推算出上一个方程解 x n − 1 , y n − 1 x_{n-1},y_{n-1} xn1yn1的值,直到得到待求方程的整数解 x 1 , y 1 x_{1},y_{1} x1y1的值。

2.3 代码(c语言)

void ex_gcd(int a, int b, int *x, int *y) { //*x和*y用来保存
	if (!b) {
		*x = 1, *y =  0;
		return ;
	}
	ex_gcd(b, a % b, x, y);
	int temp;
	temp = *x;
	*x = *y;
	*y = temp - a / b * (*y);
	return ;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值