今天看了好长时间的数论知识点,学完之后,过了一个假期,再回头看扩展欧几里得时已经是
于是我上网找到了它的证明!
(叙述的可能会非常啰嗦详细)
辗转相除法, 又名欧几里德算法,是求最大公约数的一种方法。它的具体做法是:用较小数除较大数,再用出现的余数(第一余数)去除除数,再用出现的余数(第二余数)去除第一余数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。
——摘自百度百科
我们想要证明 a a 和 b b 的最大公约数和 b b 和 a mod b a m o d b 的最大公约数相等,即 gcd(a,b)=gcd(b,a mod b) g c d ( a , b ) = g c d ( b , a m o d b )
可以令 a=kb+r a = k b + r ,则 r=a−kb r = a − k b ,其中 k=⌊a/b⌋ k = ⌊ a / b ⌋ ,( ⌊x⌋ ⌊ x ⌋ 表示向下取整),那么 r=a mod b r = a m o d b 。
若 a a , b b 的一个公约数为 d d ,则 a a , b b 都可以被 d d 整除,同时 r r 也可被 d d 整除(这里可以自己想一下)。所以 d d 是 b b 和 a mod b a m o d b 的公约数。
若 b b 和 a mod b a m o d b 的一个公约数为 d d ,则 b b , r r 可以被 d d 整除,同时 a=kb+r a = k b + r ,所以 d d 也是 a a 和 b b 的公约数。
综上, a,b a , b 和 b,a mod b b , a m o d b 的公约数是一样的,其最大公约数也必然相等。
实现:
辗转相除法是我们很早的时候就了解的算法,实现也有很多种方法,可以用递归或非递归的方式实现,这里就不再给出
(就是对欧几里得算法的扩展)
扩展欧几里得算法可以用来求解线性同余方程和乘法的逆元。
线性同余方程的解法步骤这里就不再赘述,扩展欧几里得算法所能实现的就是:给定 a a , b b ,求解 x x , u u ,使之满足 ax+by=gcd(a,b)=d a x + b y = g c d ( a , b ) = d 。接下来给出过程及证明
已知: ax+by=1 a x + b y = 1 且 a a , b b 互质
求: x x , y y
ax+by=1=gcd(a,b) a x + b y = 1 = g c d ( a , b )
根据朴素的辗转相除法得: gcd(a,b)=gcd(b,a mod b) g c d ( a , b ) = g c d ( b , a m o d b )
所以: ax+by=gcd(b,a mod b)=bx1+(a mod b)y1 a x + b y = g c d ( b , a m o d b ) = b x 1 + ( a m o d b ) y 1
又因为: a mod b=a−⌊a/b⌋∗b a m o d b = a − ⌊ a / b ⌋ ∗ b
所以展开并移项得:
ax+by=bx1+(a−⌊a/b⌋∗b)y1 a x + b y = b x 1 + ( a − ⌊ a / b ⌋ ∗ b ) y 1
ax+by=bx1+ay1−b∗⌊a/b⌋y1 a x + b y = b x 1 + a y 1 − b ∗ ⌊ a / b ⌋ y 1
ax+by=ay1+b(x1−⌊a/b⌋∗y1) a x + b y = a y 1 + b ( x 1 − ⌊ a / b ⌋ ∗ y 1 )
所以: x=y1 x = y 1 , y=x1−⌊a/b⌋∗y1 y = x 1 − ⌊ a / b ⌋ ∗ y 1 ,这就是 x x , y y 与 x1 x 1 , y1 y 1 的关系
像这样递归下去,直到 b=0 b = 0 ,此时 anxn+0∗yn=gcd(an,0)=an a n x n + 0 ∗ y n = g c d ( a n , 0 ) = a n ,那么 xn=1 x n = 1 , yn=任意数 y n = 任 意 数 ,为了方便,我们取 y=0 y = 0 .
之后进行回溯, x=y1 x = y 1 , y=x1−⌊a/b⌋∗y1 y = x 1 − ⌊ a / b ⌋ ∗ y 1 ,最后就做到了在求解 a a , b b 的最大公约数的过程中也实现了对 x x , y y 的求解,这也是这个算法叫做扩展欧几里得的原因。
网上扩展欧几里得算法的模板很多,这里给出一个:
int exgcd(int a,int b)
{
if(b==0)//边界
{
x=1;
y=0;//y可以为任意数,这里取0
return a;
}
int r=exgcd(b,a%b);
int t=x;
x=y;//更新解的过程
y=t-a/b*y;//更新解的过程
return r;
}
这里再推荐两个博客,也是有关证明的,可以看一下
https://blog.csdn.net/lincifer/article/details/49391175
http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
结束了。
有不严谨的地方还请指正。