為什么算法成對出現?因為它們確實關系很密切呀。
前置芝士:裴蜀定理
裴蜀定理得名於法國數學家艾蒂安·裴蜀,說明了對任何整數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; }