題目描述
求關於 x 的同余方程 ax ≡ 1 (mod b)的最小正整數解。
輸入輸出格式
輸入格式:
輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。
輸出格式:
輸出只有一行,包含一個正整數 x0,即最小正整數解。輸入數據保證一定有解。
輸入輸出樣例
說明
【數據范圍】
對於 40%的數據,2 ≤b≤ 1,000;
對於 60%的數據,2 ≤b≤ 50,000,000;
對於 100%的數據,2 ≤a, b≤ 2,000,000,000。
NOIP 2012 提高組 第二天 第一題
題解
順便把歐幾里得算法也寫上了
證明:
其實歐幾里得算法就是輾轉相除法。。。
擴展歐幾里得就是
對於不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然
存在整數對 x,y ,使得 gcd(a,b)=ax+by。
求解 x,y的方法的理解
設 a>b。
1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;
2,a>b>0 時
設 ax1+ by1= gcd(a,b);
bx2+ (a mod b)y2= gcd(b,a mod b);
根據朴素的歐幾里德原理有 gcd(a,b) = gcd(b,a mod b);
則:ax1+ by1= bx2+ (a mod b)y2;
即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根據恆等定理得:x1=y2; y1=x2- [a / b] *y2;
這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基於 x2,y2.
上面的思想是以遞歸定義的,因為 gcd 不斷的遞歸求解一定會有個時候 b=0,所以遞歸可以結束。
代碼
//by 減維 #include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> #include<map> #include<bitset> #include<algorithm> #define ll long long #define maxn using namespace std; ll n,m; ll gcd(ll x,ll y) { return y?gcd(y,x%y):x; } ll exgcd(ll a,ll b,ll &x,ll&y) { if(b==0){ x=1,y=0; return a; } ll q=exgcd(b,a%b,y,x); y-=a/b*x; return q; } int main() { scanf("%lld%lld",&n,&m); ll z=gcd(n,m); n/=z,m/=z; ll x,y; ll asd=exgcd(n,m,x,y); printf("%lld",(x+m)%m); }