[數論][exgcd]同余方程
題目描述
求關於 x 的同余方程 ax ≡ 1 (mod b)的最小正整數解。輸入
輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。輸出
輸出只有一行,包含一個正整數 x0,即最小正整數解。輸入數據保證一定有解。樣例輸入
3 10
樣例輸出
7
提示
對於 100%的數據,2 ≤a, b≤ 2,000,000,000。
思路:exgcd的應用——求解不定方程、求解線性同余方程
-----------------------------------------------------------------------------
下面給出關於ecgcd的詳解與模板:(以下討論的數全為整數)
問題1:給出方程 ax+by=gcd(a,b) ,求解滿足方程的x,y的一組解(求解不定方程)
解: 構造一個相同形式的方程——bx1+(a%b)y1=gcd(b,a%b)
聯立上述兩個方程:因為由歐幾裏得定理有gcd(a,b)=gcd(b,a%b),所以ax+by=bx1+(a%b)y1
因為a%b=a-a/b*b,帶入上式並整理得ax+by=ay1+b(x1-a/b*y1)
對比等式左右兩邊得x=y1 , y=x1-a/b*y1
因此,若知道滿足方程bx1+(a%b)y1=gcd(b,a%b)的x1,y1的一組解,就可以得出x,y的一組解
同理關於方程bx1+(a%b)y1=gcd(b,a%b)的求解也可以用同樣的方法由相應的x2,y2得出
如此遞歸下去,當遞歸到最底層b=0時,顯然方程的一組解為x=1,y=0
得到這組解後,便可以回溯得到最頂層方程即ax+by=gcd(a,b)的一組解了。
引理:存在 x , y 使得 ax+by=gcd(a,b)
上述解法,我們可以用遞歸的方法來實現。
void exgcd(ll a,ll b){//x,y為兩參數,a,b為兩參數的系數 if(b==0) y=(x=1)-1;//x,y為全局變量 else{ exgcd(b,a%b); ll tmp=x; x=y; y=tmp-a/b*y; } }
上述代碼實現了求方程ax+by=gcd(a,b)的一組解x和y,可以由這一組解得到方程的其他多組解:(設x0,y0為一組已知解,x,y為通解)
x=x0+b/gcd(a,b)*k
y=y0+a/gcd(a,b)*k (其中k為整數)
將通解帶入原方程即可驗證。
問題2:給出方程 ax+by=r,求解滿足方程的x,y的一組解(求解不定方程)
解: 當r%gcd(a,b)!=0時,方程無整數解
當r%gcd(a,b)==0時,先利用exgcd求出方程ax+by=gcd(a,b)的一組解x0,y0,則有ax+by=r的一組解為x1=x0*r/c,y1=y0*r/c
原方程的通解為 x=x1+b/gcd(a,b)*k
y=y1+a/gcd(a,b)*k
問題3:求關於 模方程 ax%b=c(ax=c(mod b))的解x(求解線性同余方程)
解:方程轉換為 ax+by=c ,即利用exgcd求不定方程的解x,y(最後只需要x的值)
原方程的通解為x=x0+b/gcd(a,b)*k(其中x0為ax%b=c的其中一解)
設s=b/gcd(a,b),則 x 的最小正整數解為 (x1%s+s)%s
-----------------------------------------------------------------------------
AC代碼:
#include <iostream> #include<cstdio> #define ll long long using namespace std; ll x,y; void exgcd(ll a,ll b){ if(b==0) y=(x=1)-1; else{ exgcd(b,a%b); ll tmp=x; x=y; y=tmp-a/b*y; } } int main() { ll a,b; scanf("%lld%lld",&a,&b); exgcd(a,b); while(x<=0) x+=b; printf("%lld\n",x); return 0; }
[數論][exgcd]同余方程