1. 程式人生 > >(數論)整數二元一次不定方程(擴充套件歐幾里得求解)

(數論)整數二元一次不定方程(擴充套件歐幾里得求解)

問題:形如a*x+b*y=c(a,b均不為0)的方程,a,b,c都是整數,求(x,y)整數解。

判斷是否有解

整數二元一次方程有解的充要條件是gcd(a,b)|c。如果不能整除則無解。

擴充套件歐幾里得演算法

歐幾里得演算法就是求出a*x+b*y=gcd(a,b)的一個解(特解)

程式碼如下:

int ex_gcd(int a,int b,int &x,int &y){
    if(b==0) {x=1;y=0;return a;}
    int d=ex_gcd(b,a%b,x,y);//求出a,b的最大公約數
    int tmp=x;x=y;y=tmp-a/b*y
; return d; }

關於上述遞迴函式中x,y變化情況證明推導如下(參考本篇文章):
由歐幾里德演算法gcd(a,b)=gcd(b,a%b),所以a*x1+b*y1=gcd(a,b)=gcd(b,a%b)=b*x2+(a%b)y2,現在只要做一些變形就可以得到擴充套件歐幾里德演算法中的用到的式子了。令k=a/b(商),r=a%b(餘數),那麼a=k*b+r。所以r=a-k*b,帶入上式,得到a*x1+b*y1=b*x2+(a-(a/b)*b)y2=a*y2+b(x2-(a/b)*y2) => x1=y2,y1=x2-(a/b)*y2。有了這兩個式子我們就知道了在用歐幾里德求最大公約數的時候,相應的引數x,y的變化。現在再回過頭來看一下擴充套件歐幾里德演算法的程式碼就很好理解了,實際上擴充套件歐幾里德就是在求a和b的最大公約數的同時,也將滿足方程a*x1+b*y1=gcd(a,b)的一組x1和y1的值求了出來。

下面是《演算法競賽入門經典》(第2版)上的擴充套件歐幾里得演算法程式碼的解釋:

void gcd(int a,int b,int &d,int &x,int &y){
    if(b==0){x=1;y=0;d=a;}
    else{
        gcd(b,a%b,d,y,x);//注意這裡x,y互相交換了一下
        y-=a/b*x;//這裡是在x,y互相交換的基礎上對y=tmp-a/b*y的改進
    }
}

通解

a*x+b*y=gcd(a,b)在有解並求出特解(x,y)的情況下,通解可以表示為
x’=x+b/gcd(a,b)*t;
y’=y-a/gcd(a,b)*t;
對於一般式a*x+b*y=c,如果有解,只需要把a*x+b*y=gcd(a,b)的特解乘上c/gcd(a,b)即可得到其特解,通解還是一樣的公式。

【例項程式碼】

#include<iostream>

using namespace std;

int ex_gcd(int a,int b,int &x,int &y){
    if(b==0) {x=1;y=0;return a;}
    int d=ex_gcd(b,a%b,x,y);//求出a,b的最大公約數
    int tmp=x;x=y;y=tmp-a/b*y;
    return d;
}

int main()
{
    int a,b,c,x,y,d;
    cin>>a>>b>>c;
    d=ex_gcd(a,b,x,y);
    if(c%d!=0) cout<<"No solution!"<<endl;
    else{
        cout<<"特解: ";
        cout<<"x="<<c/d*x<<", y="<<c/d*y<<endl;
        cout<<"其他一個解: ";
        cout<<"x="<<c/d*x+(b/d*c)/(d*c/d)<<", y="<<c/d*y-(a/d*c)/(d*c/d)<<endl;
    }
    return 0;
}

相關推薦

數論整數二元不定方程擴充套件求解

問題:形如a*x+b*y=c(a,b均不為0)的方程,a,b,c都是整數,求(x,y)整數解。 判斷是否有解 整數二元一次方程有解的充要條件是gcd(a,b)|c。如果不能整除則無解。 擴充套件歐幾里得演算法 歐幾里得演算法就是求出a*x+b*y=g

解的個數直線上的點數論-擴充套件演算法

Description  已知x,y滿足如下條件:  ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均為整數。  其中:a,b,c,x1,x2,y1,y2 都是絕對值不超過 10^8 的整數。  求(x,

POJ 2115 for求迴圈次數-數論-同餘方程+擴充套件演算法

題意:給定for迴圈的初始值,結束值和增量,還有一個模,求最少的迴圈次數。 分析: 讀完題後應該就知道是一個同餘的概念,所以就是解一個一元一次同餘方程,像上題一樣用擴充套件歐幾里得演算法。這題的trick點是k最大為32,那麼2^32超出了int,要用long long,所

POJ-1061-青蛙的約會 擴充套件演算法

原題連結: http://poj.org/problem?id=1061 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定

HDU-2669-Romantic 擴充套件演算法

原題連結: http://acm.hdu.edu.cn/showproblem.php?pid=2669 The Sky is Sprite. The Birds is Fly in the Sky. The Wind is Wonderful. Blew Throw the Trees

POJ-2142-The Balance 擴充套件演算法

原題連結: Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspiri

51nod 1256 乘法逆元擴充套件演算法

思路1:把k*M%N=1可以寫成一個不定方程,(k*M)%N=(N*x+1)%N,那麼就是求k*M-N*x=1使得k最小,不定方程利用擴充套件歐幾里得演算法 --------------------------------------------------------

同餘式的求解擴充套件

大佬的解釋 題目連結 一次同餘式a*x%n=b的解的存在條件是b整除gcd(a,n)。 #include<cstdio> #include<cstring> #includ

擴充套件德演算法解二元不定方程

擴充套件歐幾里德演算法: 已知兩個不完全為 0 的非負整數 a,b,必然存在整數對 x,y ,使它們滿足貝祖等式: 解一定存在,根據數論中的相關定理。下面給出程式碼: int extgcd(int a, int b, int& x, int& y)

數論擴充套件方程整數

A - Solutions to an Equation You have to find the number of solutions of the following equation: Ax + By + C = 0 Where A, B, C, x, y 

ZOJ ~ 3593 ~ One Person Game 擴充套件不定方程

題意 你要從A走到B,你每次可以走a步,b步,a+b步問最小需要走多少步?無法到達輸出 -1。 題解 先不考慮a+b步的情況,那麼我們要求解的就是:,如果,證明無解。 假設原方程一組解為x0,y0,那麼通解(x,y)為:,。 其實也就是兩條直線:, 取一條平行於

Wannafly summer camp Day2  ——Utawarerumono數論擴充套件

9511: Utawarerumono 時間限制: 1 Sec  記憶體限制: 128 MB 提交: 389  解決: 66 [提交] [狀態] [討論版] [命題人:admin] 題目描述 算術是為數不多的會讓久遠感到棘手的事情。通常她會找哈克幫忙,但是哈克已經被

同餘問題——擴充套件exgcd

前言 擴充套件歐幾里得演算法是一個很好的解決同餘問題的演算法,非常實用。 歐幾里得演算法 簡介 歐幾里得演算法,又稱輾轉相除法。 主要用途 求最大公因數gcdgcdgcd。 公式 gcd(a,b)=g

演算法學習——德演算法&擴充套件演算法

最大公約數/歐幾里德演算法(gcd) 歐幾里德演算法又稱輾轉相除法,證明可以度娘。 個人簡單腦部就是a和b兩個數的模還是a和b的最大公約數 int型別  int gcd(int a, int b) {return a%b==0?b:gcd(b,a%b);} long l

擴充套件演算法乘法逆元 最小正整數解 直線上的整數點

參考資料: 本文證明過程來自百度百科和劉汝佳的演算法入門經典。 擴充套件歐幾里得演算法介紹: 前置知識:歐幾里得演算法(其實就是輾轉相除法,用於計算兩個整數a,b的最大公約數。) 歐幾里得演算法: 在開始之前,我們先說明幾個定理: gcd(a,b)=gcd(b,a

C. Line擴充套件不定方程的解

time limit per test 1 second memory limit per test 256 megabytes input standard input outp

一點初等數論擴充套件,求逆元的三種方法

以前遇到數論題直接懵逼,今天開始好好搞搞基礎的數論知識。 一下內容證明我可能會省略,畢竟我太弱了…. . . . . . 1.模運算 幾個常用的定律: ( a + b ) mod p = ( a mod p + b mod p ) mod

青蛙的約會擴充套件演算法+不定方程求解

1.折磨了我好久,不過大概是懂了。 2.題目: 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面

擴充套件應用:求解不定方程、解模線性方程、求模的逆元

歐幾里得 1.含義:歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。 原理公式:gcd(a,b)=gcd(b,a mod b) 因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等. 2.實現: int gcd(int a

同餘定理演算法

如果  (a-b)%m==0  那麼 a%m==0  b%m==0 a,b關於模m同餘。   求最大公約數 #include "pch.h" #include<iostream> #include<cstdio> #include<