欧几里得+拓展欧几里得
(1)知识支持:
定理1:
Gcd(a,b) = Gcd(-a,b) = Gcd(a,-b) = Gcd( |a| , |b| )。
定理5:
设 Gcd(m,a) = 1,则有 Gcd(m,ab) = Gcd(m,b),这就是说“求 m 与另一个数的最大公约数时,可以把另一个数中与 m 互素的因数去掉”。
定理6:
设 Gcd(m,a) = 1,那么若 m | ab,则 m | b,这就是说“若一个数被 m 整除,则把这个数中与 m 互素的因数去掉后仍被 m 整除”。
定理7:
Lcm(a,b)*Gcd(a,b) = |ab|。
(2)欧几里得算法:
欧几里得算法是用来求 a 和 b 的最大公公约数(Greatest Common Divisor)的算法。
那么由欧几里得算法可得:
Gcd(a,b) = Gcd(b%a , a);
证明欧几里得算法正确性的关键是证明 Gcd(a,b)=Gcd(b%a,a); 令x=Gcd(a,b),y=Gcd(b%a,a); b%a可表示为a和b的线性组合:b%a=b-(b/a)*a; 因为 a%x=0,b%x=0; 所以 (b%a)%x=0; 故y%x=0; 又(b%a)%y=[b-(b/a)*a]%y=0,a%y=0; 根据同余定理可得 b%y-(b/a)*a%y=0,所以b%y=(b/a)*a%y=0; 所以x%y=0; 所以Gcd(a,b)=Gcd(b%a,a); 证毕;
(2)拓展欧几里得算法:
线性组合定义:
如果 a 和 b 都是整数,则 ax+by 是 a 和 b 的线性组合,其中 x,y 为整数。
定理1:
设 c 是 a 和 b 的线性组合中的最小正整数,即 ax+by = c,(x,y为整数)。
则 c = Gcd(a,b);
定理1证明:
定理2:
如果 a 和 b 都是整数,则存在整数 x,y 使得 ax+by = Gcd(a,b);
推论:
整数 a 和 b 互素,当且仅当存在 x,y 使得 ax+by = 1;
给出不定方程 ax+by = Gcd(a,b) ,拓展欧几里得算法可以用于求解不等方程组的整数根(x,y)。
拓展欧几里得算法:
1 /** 2 求解满足ax+by=Gcd(a,b)的所有解(x,y) 3 */ 4 #include<iostream> 5 #include<cstdio> 6 using namespace std; 7 8 int extendGcd(int a,int b,int &x,int &y) 9 { 10 if(a == 0) 11 { 12 x=0,y=1; 13 return b; 14 } 15 16 int gcd=extendGcd(b%a,a,x,y); 17 int x2=x,y2=y; 18 y=x2; 19 x=y2-b/a*x2; 20 21 // 第16~19可简化为 22 // int gcd=extendGcd(b%a,a,y,x); 23 // x -= b/a*y; 24 25 return gcd; 26 } 27 int main() 28 { 29 int a,b; 30 while(~scanf("%d%d",&a,&b)) 31 { 32 int x,y; 33 int gcd=extendGcd(a,b,x,y); 34 printf("%d*%d+%d*%d=%d\n",a,x,b,y,gcd); 35 } 36 }
定理3:
方程 ax+by = c 有解的充要条件是 Gcd(a,b) | c,当 ax+by = c 有解时,他的解和方程
的解相同。
假设 (x0,y0)是 ax+by = c 的一组解,那么 ax+by = c 的所有整数解为:(k为整数)
x = x0+k×[ b/Gcd(a,b) ];
y = y0-k×[ a/Gcd(a,b) ];