1. 程式人生 > >擴展歐幾裏德算法~易懂版

擴展歐幾裏德算法~易懂版

amp 決定 space 變換 擴展歐幾裏德算法 main algo 代碼 temp

之前一直知道擴展歐幾裏德算法的實現代碼,但是原理一直還是模模糊糊,看了很多終於明白了,於是決定寫一篇來記錄下自己的思路。

下面實現的其他定理就不再多解釋了,主要講擴展歐幾裏德算法。

擴展歐幾裏德算法就是用來求 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;
}

擴展歐幾裏德算法~易懂版