本篇將附上擴展歐幾里得算法的思想與推導;
對於一個方程\(a*x+b*y=gcd(a,b)\)來說,我們可以做如下的推導:
設有\(a*x_1+b*y_1=gcd(a,b)\);
同時我們有\(b*x_2+(a\%b)*y_2=gcd(b,a\%b)\);
對於這個方程組,我們希望知道的是\(x_1,x_2,y_1,y_2\)之間的關系,這樣我們才可以遞歸解決這個問題
我們觀察\(b*x_2+(a\%b)*y_2\)這個式子,我們可以將\((a\%b)\)寫作\((a-\lfloor\frac{a}{b}\rfloor*b)\),將括號打開常數\(a,b\)合並,合並之后的結果為\(a*y_2+b*(x_2-\lfloor\frac{a}{b}\rfloor*y_2))\)
由於歐幾里得算法的原理\(gcd(a,b)==gcd(b,a\%b)\),我們將兩式子聯立,對比系數即可得到\(x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor*y_2\)
這個遞歸的邊界是什么呢?我們知道,當朴素歐幾里得到達邊界時,\(return\ gcd(a,0)=a\),那么邊界條件就是對\(a*x_0+b*y_0=a\)求解,很顯然,此時\(x_0=1,y_0=0\)
當我們遞歸求出了一個方程的特解時,如何求出這個方程的通解呢?
方程\(a*x+b*y=gcd(a,b)\)中,如果將x加上一個常數\(k_1,y\)減去一個常數\(k_2\),仍然保持原方程成立,那么\(x+k_1,y-k_2\)就是方程的一個新解,這個k應該如何選擇呢?
實際上很簡單,\(a*(x+k_1)+b*(y+k_2)=gcd(a,b)\),打開括號,\(a*x+a*k_1+b*y-b*k_2=gcd(a,b)\);
我們保證原方程成立,就需要\(a*k_1==b*k_2\),那么顯然\(k_1=b,k_2=a\)是一種合理的情況,但是這樣是無法包含所有整數解的,因為我們加上的這個值並非是最小值
那我們應該加上什么值才行呢?我們發現當\(a*k_1==b*k_2=t*lcm(a,b)\)可以保證得到所有解,於是每次尋找解就可以分別在\(x\)加上\(\frac{b}{gcd(a,b)},在y減去\frac{a}{gcd(a,b)}\)就可以了
對於方程\(a*x+b*y=c\)我們又該如何求解?我們發現如果\((c\%gcd(a,b)!=0)\)那么這個方程是無解的,而如果\(gcd(a,b)*t==c\),我們就可以按上面的方法求解之后對我們的解乘上一個\(t(t=\frac{c}{gcd(a,b)})\)
\(code:\)
int exgcd(int a,int b,int &x1,int &y1)
{
if(!b)
{
x1=1,y1=0;
return a;
}
int x2,y2;
int d=exgcd(b,a%b,x2,y2);
x1=y2,y1=x2-(a/b)*y2;
return d;
}