如何使用拓展歐幾裏得算法求解模線性方程組(詳解)
式子a≡b(mod n)稱為a和b關於模n同余,它的充要條件是a-b是n的整數倍,即a-b=zn(其中z取整數)。
而模線性方程組ax≡b(mod n)可以寫成ax-b=zn(其中z取整數),移項可得
ax-zn=b,也即二元一次方程ax+by=c的形式,利用拓展歐幾裏得算法(extgcd)可以求解該方程是否有解及其一組解,並可根據該組解寫出解系,進而求出一個特解,比如最小正整數解。
下面給出拓展歐幾裏得算法的程序。
1 typedef long long LL; 2 void extgcd(LL a, LL b, LL &d, LL &x0, LL &y0)3 { 4 if(b == 0){ 5 d=a;x=1;y=0; 6 } 7 else{ 8 extgcd(b,a%b,d,y,x); 9 y -= x*(a/b); 10 } 11 }
其中a,b是系數,d表示a,b的最大公約數,x0,y0表示一組特解。
由gcd(a,b)= gcd(b,a%b)
得ax0 + by0 = gcd(a, b) = gcd(b, a%b) = bx1 + (a%b)y1
其中a%b又可以寫成a-a/b*b,
故又=bx1 + (a-a/b*b)y1
整理得 ay1 + b(x1-a/b*y1)
由系數相等的x0=y1,y0=(x1-a/b*y1);那麽只要求出x1和y1即可求得x0和y0,故向下遞歸求x1,y1,如此遞歸一直求到gcd(an, 0) = an*xn + 0 * yn時,令xn=1,yn=0可滿足該式,因為an*1+0*0=an=gcd(an, 0)。之後遞歸回退,直至求出x0,y0,而d也即a和b的最大公約數。
下面說如何判斷是否存在整數解。
將ax+by=c兩邊同時除以d可得
a/d*x+b/d*y=c/d,因為d為a和b的最大公約數,所以a/d和b/d均為整數,故要求x和y的整數解,c/d必須為整數,否則無整數解。
綜上,有如下結論:設a,b,c為任意整數,d=gcd(a,b),d=ax+by,若c是d的倍數,則存在整數解,否則不存在整數解。
下面說如何根據求得的一組解(x0,y0)求出解系,進而求出一組特解。
先用帶入擴展歐幾裏得得出ax+b*y=gcd(a,b)的一個解x0,y0;
再觀察兩個式子:
ax+b*y=c 0)
a*x0+b*y0=d 1) ( 令d=gcd(a,b) )
將0)式兩邊都除以d,得:
x*(a/d)+y*(b/d)=c/d
將1)式兩邊都乘以b/d與0)式比較:
(x0*c/d)*a + (y0*c/d)*b=c
a*x+b*y=c 0)
得x=x0*c/d,y=y0*c/d;
再將上面的結論完善一下:設a,b,c為任意整數,d=gcd(a,b),方程d=ax+by的一組解是(x0,y0),當c是d的倍數,則線性方程組ax+by=c的一組解是(x0*c/d,y0*c/d),當c不是d的倍數時無整數解。
接下來將一個解擴展成一個解系:
1)除以d得: x0*(a/d)+y0*(b/d)=1
因為(a/d)和(b/d)互質,將方程寫成:
(x0+u*(b/d))*(a/d)+(y0+v*(a/d))*(b/d)=1即只需u*(b/d)*(a/d) + v*(a/d)*(b/d)=0即可;
所以x,y的解系可以寫成 x=(x0+u*(b/d))*(a/d)
y=(y0+v*(a/d))*(b/d)
接下來就可以求滿足方程的x的最小正整數了
所以xmin=(x0*(c/d)) mod (b/d)
具體例子是POJ的1061 青蛙的約會
https://www.cnblogs.com/wenzhixin/p/9343420.html
如何使用拓展歐幾裏得算法求解模線性方程組(詳解)