欧几里得算法
又称辗转相除法,用来计算两个数的最大公约数
int gcd(int a, int b){ if(b==0) return a; else return gcd(b,a%b); }
gcd函数的基本性质
gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)
gcd(a,b)=gcd(b,a mod b)
扩展欧几里得
扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =d
对于不完全为0的非负整数,a,b,必然存在无数对整数对x,y,使得ax+by=gcd(a,b)
int exgcd(int a, int b)//拓展欧几里德 { if(b == 0) { x = 1; y = 0; return a; } int d = exgcd(b, a%b); int t = x; x = y; y = t - a/b*y; return d; }
证明:
设a*x + b*y= gcd(a,b) 下一个状态 b*x1 + (a%b)*y1 = gcd(b,a%b)
a%b = a - (a/b)*b
gcd(b,a%b) = b*x1 + (a-(a/b)*b)*y1
= b*x1 + a*y1 – (a/b)*b*y1
= a*y1 + b*(x1 – a/b*y1)
根据朴素欧几里得算法得:
gcd(a,b) = gcd(b,a mod b) 所以得a*y1 + b*(x1 – a/b*y1) =a*x+b*y
x = y1
y = x1 – a/b*y1
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int a, b, x, y; 6 int gcd(int m, int n)//欧几里德 7 { 8 int t; 9 while(n) 10 { 11 t = n; 12 n = m % n; 13 m = t; 14 } 15 return m; 16 } 17 18 //int gcd(int a, int b){ 19 // if(b==0) 20 // return a; 21 // else 22 // return gcd(b,a%b); 23 //} 24 25 int exgcd(int a, int b)//拓展欧几里德 26 { 27 if(b == 0) 28 { 29 x = 1; 30 y = 0; 31 return a; 32 } 33 int d = exgcd(b, a%b); 34 int t = x; 35 x = y; 36 y = t - a/b*y; 37 return d; 38 } 39 40 int main() 41 { 42 int a, b; 43 while(~scanf("%d%d",&a, &b)) 44 { 45 printf("%d ",gcd(a, b)); 46 int g = exgcd(a, b); 47 if(g == 1)//ax + by = 1 48 { 49 while(x < 0) 50 { 51 x += b; 52 y -= a; 53 } 54 printf("%d %d ",x,y);//x>0最小整数解 55 } 56 else 57 printf("sorry "); 58 } 59 return 0; 60 }
扩展欧几里得最大的应用就是求乘法逆元 (a*m)%b=1 称m为
ma+nb=1 m为a模b的乘法逆元 n为b模a的逆元