1. 程式人生 > 實用技巧 >基礎數論--擴充套件歐幾里得演算法

基礎數論--擴充套件歐幾里得演算法

正常的歐幾里得演算法

1 int gcd(int a,int b){
2     return b==0?a:gcd(b,a%b);
3 }

可以在O(n)的時間複雜度內,求出a和b兩數的最大公約數。

而擴充套件歐幾里得演算法則可以在求出最大公約數的同時,求出兩個數x,y,使得x*a+y*b=gcd(a,b),用處就是可以用來求解線性同餘方程(寫在下邊)

 1 //推薦第二種寫法
 2 #include<iostream>
 3 using namespace std;
 4 int exgcd1(int a,int b,int& x,int& y){
 5     if
(b==0){ 6 x=1,y=0; 7 return a; 8 }else{ 9 int d=exgcd1(b,a%b,x,y); 10 int t=y; 11 y=x-(a/b)*y; 12 x=t; 13 return d; 14 }   15 } 16 int exgcd2(int a,int b,int& x,int& y){ 17 if(b==0){ 18 x=1,y=0; 19 return a; 20 }else
{ 21 int d=exgcd2(b,a%b,y,x); 22 y=y-(a/b)*x; 23 return d; 24 } 25 } 26 int main(void){ 27 int n; 28 cin>>n; 29 for(int i=0;i<n;i++){ 30 int a,b,x,y; 31 cin>>a>>b; 32 exgcd2(a,b,x,y); 33 cout<<x<<" "
<<y<<endl; 34 } 35 return 0; 36 }

第一種證明,第二種類似

求解同餘方程

同餘方程的定義,給定a,b,m,求出一個滿足條件的x,使得a*x=b(mod m)。

也就是a*x=b+y*m,令y′=-y,得

x*a+ y′ *m=b,這就和上邊的擴充套件歐幾里得完全符合

 1 #include<iostream>
 2 using namespace std;
 3 typedef long long LL;
 4 int exgcd(int a,int b,int& x,int& y){
 5     if(b==0){
 6         x=1,y=0;
 7         return a;
 8     }else{
 9         int d=exgcd(b,a%b,y,x);
10         y=y-(a/b)*x;
11         return d;
12     }
13 }
14 int main(void){
15     int n;
16     cin>>n;
17     for(int i=0;i<n;i++){
18         int a,b,m;
19         int x,y;
20         cin>>a>>b>>m;
21         int d=exgcd(a,m,x,y);
22         if(b%d==0){
23             cout<<(LL)(b/d)*x%m<<endl;//%m是為了保證答案在m的範圍內
24                                       //% m 仍然是正確的是因為,相當於將y′增加了
25         }else{
26             cout<<"impossible"<<endl;
27         }
28     }
29     return 0;
30 }

既然能解同餘方程的話,那就能夠求逆元,只不過逆元是更加特殊的情況,b=1

具體的可以翻一翻部落格。