gcd 和 同餘方程(Exgcd)
阿新 • • 發佈:2019-08-18
求關於x的同餘方程 ax≡1(mod b) 的最小正整數解。
對於 100%的資料,2≤a,b≤2*109。
NOIP 2012 提高組 第二天 第一題
(只看Exgcd的自行跳過這段文字) 先撇開擴充套件歐幾里得什麼的不管,首先證明輾轉相除法。 gcd(greatest common divisor),是一種計算兩個數最大公約數的演算法,時間複雜度為O(1)。簡單來說,我們定義gcd(a,b)為a、b的最大公約數,那麼gcd(a,b)=gcd(b,a mod b)。一般使用遞迴計算,在最後一層,a≡0(mod b)的時候,這一層的b即為答案。 下面給出證明: 令a>b,則存在正整數k、r,使得a=kb+r,而r≡a(mod b),所以我們要證明的結論就是gcd(a,b)=gcd(b,r)。 若r=0,那麼以上結論顯然。 那麼,若r≠0呢? 假設gcd(a,b)=d,那麼存在正整數p、q,使得a=pd,b=qd(p>q)。 所以pd=kqd+r,整理得r=(p-kq)d。因為r>0,所以pd>kqd,顯然p-kq為正整數,所以r必為d的倍數,不難證明gcd(a,b)=gcd(b,r),也就是gcd(a,b)=gcd(b,a mod b)。1 #include<bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 5 LL a,b;//不開long long見祖宗 6 7 LL gcd(LL a,LL b) 8 { 9 if(b==0) return a; 10 return gcd(b,a%b); 11 } 12 int main(){ 13 scanf("%d%d",&a,&b); 14 printf("%lld",gcd(a,b)); 15 return 0; 16 }
踏入正題~ 問題是求解同餘方程 ax≡1(mod b) 的最小正整數解。 將問題轉化一下,這個方程的實質是ax+by=1(其中y為整數)。 擴歐求的是ax+by=gcd(a,b)的解。 那顯然,這裡的gcd(a,b)=1,所以這裡a,b互質。 擴充套件歐幾里得演算法~前置知識:輾轉相除法。 對於ax+by=gcd,輸入中已經給了a、b我們只要求出一組x,y解,滿足x是無陣列解中最小的正整數。 假設我們求出了另一組數x2、y2,使得bx2+(a mod b)y2=gcd(b,a mod b),則因為gcd(a,b)=gcd(b,a mod b),所以bx2
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 5 int a,b,x,y; 6 7 void Exgcd(int a,int b) 8 { 9 if(b==0) 10 { 11 x=1,y=0;//最終的x、y 12 return; 13 } 14 Exgcd(b,a%b); 15 int tmp=x; 16 x=y;//更新上一層x 17 y=tmp-(a/b)*y;//更新上一層y 18 } 19 signed main()//main函式不能為long long 20 { 21 scanf("%lld%lld",&a,&b); 22 Exgcd(a,b); 23 x=(x%b+b)%b;//最小正整數解 24 cout<<x<<endl; 25 return 0; 26 }
數學題多手算模擬幾遍就理解了~