1. 程式人生 > >如何使用拓展歐幾裏得算法求解模線性方程組(詳解)

如何使用拓展歐幾裏得算法求解模線性方程組(詳解)

得出 bsp 次方 及其 根據 約數 www 求解 回退

  式子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即可;
所以xy的解系可以寫成 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

如何使用拓展歐幾裏得算法求解模線性方程組(詳解)