为什么算法成对出现?因为它们确实关系很密切呀。
前置芝士:裴蜀定理
裴蜀定理得名于法国数学家艾蒂安·裴蜀,说明了对任何整数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 使得:
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; }