扩展欧几里得算法 and 乘法逆元

为什么算法成对出现?因为它们确实关系很密切呀。

前置芝士:裴蜀定理

裴蜀定理得名于法国数学家艾蒂安·裴蜀,说明了对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性丢番图方程(称为裴蜀等式): ax + by = m 有解当且仅当m是d的倍数。

(大忙人跳过上面的屁话)

一句话说出来就是对于方程: a*x + b*y = m有解,当且仅当 m是gcd(a,b)的整数倍

啊这个证明我不会,因为我菜

 

FAQ:(这玩意跟扩展欧几里得定理和乘法逆元什么关系啊!!)

A:正当关系

 

那么乘法逆元是什么啊?

 

乘法逆元是酱紫的:对于一组数a,b,求a在模b意义下的逆元相当于求解一个数    使得:

t*a  ≡ 1 (mod b)

然后这个式子可以变形:  t * a = b*k + 1(k是一个正整数)      ------→  t*a - b*k =1

 

这不就是裴蜀定理的形式了吗?对于这个方程如果要有解,那么1要是gcd(a,b)的倍数咯?

那就意味着gcd(a,b)必须等于1咯?

没错!对于a,b如果要使得a在模b的意义下存在逆元的充要条件为:   a与b互质

那么就可以解这个方程了呀,解出这个方程乘法逆元不也就求出来了吗?

WTF?怎么解呀?众所周知两个未知数一个方程,这个方程是有多个解的啊!

没关系直接来整一个解x0,y0使得 x0*a +y0* b=gcd(a,b)

 

这时候,扩展欧几里得算法就出来整事情了。(是不是跟gcd有关的都离不开欧几里得啊QAQ)

 还记得GCD(a,b)中递归求解a,b的最大公因数的过程了吗?

其终止条件:if(b==0)return a;

如果b == 0 的时候,这样子就意味着我们已经知道了"a,b"的最大公因数是a了

得到一组解是:x = 1 ,y = 0,这时候 a*1 + b*0 = gcd(a,b)(因为此刻a和b都不是初始状态下的a,b了,此刻a=gcd(a,b),b=0)

这时候递归返回这一组解到上一层。

 

因为是递归求解gcd,求了a,b的gcd,下一步就是求 b,a%b的gcd,但是其实这里的 a,b的gcd和 b,a%b的gcd其实是相等的(不然我们怎么递归求解)

所以假如我们知道了   一组解x1,y1使得  b*x1 + (a%b)   *  y1  =gcd(a,b)

那么x1,y1这组解和x以及y有没有关系呢?

不妨考虑对:  b*x1 + (a%b)   *  y1  =gcd(a,b)这个式子变形

 

a%b =   a-(a/b)*b  (这里的"/"表示整除,向下取整,例如 5/2 = 2,3/2=1)

 

那么b*x1+(a-(a/b)*b)*y1=gcd

所以b*x1+a*y1-(a/b)*b*y1=gcd

         a*y1+b*(x1-(a/b)*y1)=gcd

所以这里求得:x=y1,y=x1-(a/b)*y1

 

接着就可以递归到第一层求得答案了啊!(这也就是为什么扩展欧几里得能求逆元的原因了!)

 继续贴上丑陋的代码:

int exgcd(int a,int b,int &x,int &y){
    if(b == 0){x=1,y=0;return a;}
    int x1,y1;
    int d=exgcd(b,a%b,x1,y1);//记得记录最大公因数
    x=y1;
    y=x1-a/b*y1;
    return d;
}

 

posted @ 2020-08-24 15:24  MYCui  阅读(223)  评论(8编辑  收藏  举报