擴展歐幾里得算法與二元一次方程的整數解

問題引入

給出整數 a , b , n ,問方程 ax + by = n 什麼時候有整數解?如何求出所有的整數解?

有解的充分必要條件是 gcd(a,b) 整除 n

簡單解釋一下,令 a = gcd(a,b) a’ , b = gcd(a,b) b’ ,有 ax + by = gcd(a,b)(a’x+b’y) = n,如果 x , y ,a’ , b’ 都是整數的話,那麼 n 必須是 gcd(a,b) 的倍數纔有解。

例如 4x+6y = 8、2x+3y = 4 有整數解,而 4x+6y = 7沒有整數解。
如果確定有解,一種解題的方法是先找到一個解(x0,y0),那麼通解就爲:
x = x0 + bt , y = y0 - at (t 是任意整數)
利用拓展歐幾里得算法便可以求出特解(x0,y0)

拓展歐幾里得算法

當方程符合ax + by = gcd(a,b)時,可用拓展歐幾里得算法求出(x0,y0),如下:

void gcdEx(int a,int b,int &x,int &y)
{
    if(b == 0){
        x=1;
        y=0;
        return;
    }
    gcdEx(b,a%b,x,y);
    int tmp = x;
    x = y;
    y = tmp - (a/b)*y;
}

求任意方程 ax + by = n 的一個整數解

用拓展歐幾里得算法得出方程 ax + by = gcd(a,b) 的一個特解後,利用它可以進一步得出任意方程 ax + by = n 的一個解,步驟如下:

  1. 判斷方程 ax + by = n 是否有整數解,有解的條件是 gcd(a,b) 可以整除 n
  2. 用拓展歐幾里得算法求 ax + by = gcd(a,b) 的一個解(x0,y0)
  3. 在 ax0 + by0 = gcd(a,b) 兩邊同時乘以 ngcd(a,b){n \above{0.5pt} gcd(a,b)} , 得:
    ax0ngcd(a,b){ax_0n \above{0.5pt} gcd(a,b)} + by0ngcd(a,b){by_0n \above{0.5pt} gcd(a,b)} = n
  4. 對照 ax + by = n,得到它的一個解(x0,y0) 爲:
    x0 = x0ngcd(a,b){x_0n \above{0.5pt} gcd(a,b)} , y0 = y0ngcd(a,b){y_0n \above{0.5pt} gcd(a,b)}

綜上總的代碼爲:

//拓展歐幾里得算法
void gcdEx(int a,int b,int &x,int &y);//參加上方

int main()
{
    int a,b,n,x(0),y(0);
    cin>>a>>b>>n;
    if(n%__gcd(a,b) == 0){ //第一步判斷方程是否有整數解
        gcdEx(a,b,x,y);//第二步求方程 ax+by=gcd(a,b) 的一個特解
        x = x*n/__gcd(a,b); //第三步計算 ax+by=n 的解
        y = y*n/__gcd(a,b);
        cout<<x<<" "<<y<<endl;
    }
    return 0;
}

應用場合

  1. 求解不定方程
  2. 求解模的逆元
  3. 求解同餘方程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章