擴展歐幾裏德算法~易懂版
之前一直知道擴展歐幾裏德算法的實現代碼,但是原理一直還是模模糊糊,看了很多終於明白了,於是決定寫一篇來記錄下自己的思路。
下面實現的其他定理就不再多解釋了,主要講擴展歐幾裏德算法。
擴展歐幾裏德算法就是用來求 Ax+By=K 的一組解, A,B,K 都是已知常量,求解 x, y.
首先,根據“貝祖等式“可知,
Ax1+By1=gcd(A,B).
所以我們可以接著推出
C =A%B.
Bx2 + Cy2 = gcd(B,C)
= Bx2 + (A%B)y2 = gcd( B, A%B )
然後我們再接著推個用到的
A%B=[A-(A/B)*B]. //這一步要註意下,這裏的 ‘A/B’是計算機中的A/B,不保留小數的
最後,我們可以來總推了
Ax1 + By1 = gcd( A, B ) .
C=A%B.
Bx2 + Cy2 = gcd( B, C ).
gcd( A, B ) = gcd( B, C ).//劃重點
所以
Ax1 + By1 = Bx2 + Cy2
Ax1 + By1 = Bx2 + ( A%B )y2
Ax1 + By1 = Bx2 + [ A - (A/B) * B ]y2
Ax1 + By1 = Bx2 + Ay2 - [ (A/B) *B]y2
根據恒等定理得
Ax1 = Ay2
By1 = Bx2 - B*[ (A/B) *y2 ] = B * [ x2 - (A/B)*y2 ]
所以
x1 = y2
y1 = x2 - (A/B)*y2
仔細觀察下這其實就是個遞推的過程
因為 x1要從 y2得來 , y1要從 x2 - (A/B)*y2得來
而 x2 要從 y3 得來 , y2要從 x3 - (A/B)*y3得來
.........................................................................
最終Xn-1 要從 Yn得來,Yn-1 要從 Xn - (A/B)*Yn
//註意,這裏的A和B的值, 每次都不一樣, A 和 B 不斷的替換為 A=B , B=A%B,其實就是gcd的參數變換
那麽這個遞推的邊界在哪裏呢?
假設 A>0 B=0
則 gcd( A, B )=A.
則 Ax + By =gcd ( A,B )
可以推出 x=1, y=0.
那麽邊界就是當 B=0的時候, 賦值 x=1,y=0 然後返回
————————————————————————————————————————分割線————————————————————————————————————————
下面給出兩個實現代碼,一個是簡單流程實現版,一個是代碼簡化版,建議看懂第一個 然後 用 第二個
//簡化版
int gcd_pro(int A, int B, int &x, int &y) { if (B == 0) { x = 1; y = 0; return A; } else { int ans; int x_temp, y_temp; x_temp = x; y_temp = y; ans=gcd_pro(B, A%B, x_temp, y_temp); x = y_temp; y = x_temp - (A / B)*y_temp; return ans; } }
//白書版
int gcd_pro(int A, int B, int &x, int &y) { if (B == 0) { x = 1; y = 0; return A; } else { int ans; ans = gcd_pro(B, A%B, y, x); y -= (A / B)*x; return ans; } }
不過,我們經常性是要解決 Ax + By=C 這樣的方程,知道了 Ax + By = gcd(A,B)的解又有什麽用呢?
沒關系,還是簡單數學推導:
Ax + By = C
Ax + By = [C * gcd(A,B)] / gcd(A,b)
A*[ x * C / gcd(A,B) ] + B*[ y* C / gcd(A,B) ] = gcd( A, B )
這樣你看,原本的 x 變成了 x * C / gcd(A,B)
這樣你看,原本的 y 變成了 y* C / gcd(A,B)
所以,我們只要把 Ax + By = gcd(A,B) 得出的 x 和 y,
乘等於 C / gcd(A,B) 就得到 Ax + By = C 的解
下面給出例子
#include<iostream> #include<algorithm> #include<string> #include<vector> #include<queue> using namespace std; int gcd_pro(int A, int B, int &x, int &y) { if (B == 0) { x = 1; y = 0; return A; } else { int ans; ans = gcd_pro(B, A%B, y, x); y -= (A / B)*x; return ans; } } int main() { int ans; int x_ans, y_ans; int A_ans, B_ans, C_ans; x_ans = y_ans = 0; cin >> A_ans >> B_ans >> C_ans; ans=gcd_pro(A_ans, B_ans, x_ans, y_ans); x_ans *= ans; y_ans *= ans; cout << ans << endl << x_ans << ‘ ‘ << y_ans << endl; return 0; }
擴展歐幾裏德算法~易懂版