1. 程式人生 > >淺談擴展歐幾裏得算法(exgcd)

淺談擴展歐幾裏得算法(exgcd)

end gpo 實現 ·· spa 通過 函數 pan 由於

在講解擴展歐幾裏得之前我們先回顧下輾轉相除法:
\(gcd(a,b)=gcd(b,a\%b)\)\(a\%b==0\)的時候b即為所求最大公約數
好了切入正題:
簡單地來說exgcd函數求解的是\(ax+by=gcd(a,b)\)的最小正整數解。根據數論的相關知識,一定存在一組解\(x,y\)使得\(ax+by=gcd(a,b)\)。那就來談談具體如何來求解吧。
根據輾轉相除法的內容\(gcd(a,b)=gcd(b,a\%b)\)我們可以得到:\[ax_1+by_1=gcd(a,b)=gcd(b,a\%b)=bx_2+a\%by_2······①\]
又由於\(a\%b=a- \lfloor a\div b\rfloor\times b\)


在計算機中\(a\%b= \lfloor a\div b\rfloor\times b=a/b*b%\)所以\[bx_2+a\%by_2=bx_2+(a-a/b*b)y_2\]
將等式①變形得:\[ax_1+b(y_1+a/ b*y_2)=ay_2+bx_2\]
因為等式左右兩邊結構相同我們可以解得:\[\begin{cases}x_1=y_2\\y_1=x_2-a/b*y_2\end{cases}\]
在擴展歐幾裏得算法的最後一步即\(b=0\)的時候,顯然有一對整數\(x=1,y=0\)使得\[a*1+0*0=gcd(a,0)\]
那麽我們就可以通過編程實現exgcd了,請仔細體驗下代碼的精妙之處:

int
exgcd(int a,int b,int &x,int &y) { if(b) { int d=exgcd(b,a%b,y,x); y-=a/b*x; } else { x=1; y=0; return a; } }

淺談擴展歐幾裏得算法(exgcd)