欧几里得算法
欧几里得算法又称辗转相除法,用于计算两个正整数的最大公约数。
辗转相除法是利用以下性质来确定两个正整数 a 和 b 的最大公因子的:
⒈ 若 r 是 a ÷ b 的余数,且r不为0, 则
gcd(a,b) = gcd(b,r)
⒉ a 和其倍数之最大公因子为 a。
另一种写法是:
⒈ 令r为a/b所得余数(0≤r
若 r= 0,算法结束;b 即为答案。
⒉ 互换:置 a←b,b←r,并返回第一步。
实现:
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int gcd(int a, int b) {
if(b == 0) return a;
else return gcd(b, a % b);
}
1 //***********************************************************************************************
2 /*
3 欧几里得算法也称辗转相除法,如果要求a,b的最大公约数,则gcd(a, b) = gcd(b, a % b),
4 直到a % b = 0,此时b就是要求的最大公约数。
5 扩展欧几里得算法是在求最大公约数的基础上求出一组x,y使得x*a + y*b = gcd(a, b)。
6 这个方程是有多解的,以下算法所求的是满足|x|+|y|最小的一组x0,y0。可以以此x0,y0表示方程
7 的通解:
8 x = x0 + (b / a) * t
9 y = y0 - (a / b) * t
10 现在我们需要求x,y使之满足a*x + b*y = gcd(a, b)。已知它的下一个状态是b*x1 + a%b*y1 = gcd(a, b)。
11 而a%b可以写成a - (a / b) * b(a/b为指的是整除)。可推得:
12 gcd(b, a % b) = b * x1 + (a - (a / b) * b) * y1
13 = a * y1 + b * (x1 - (a / b) * y1)
14 gcd(a, b) = a * x + b * y
15 所以:
16 x = y1;
17 y = x1 - (a / b) * y1
18 在最终状态时, a = gcd, b = 0。此时就领x = 1, y = 0。(y可以是任何值,等于0时求出来的特解就是
19 |x| + |y|最小的解)。
20 */
21 //************************************************************************************************
22
23 #include<iostream>
24 #include<cstdio>
25 #include<cstdlib>
26 #include<conio.h>
27
28 using namespace std;
29
30 int gcd(int a, int b) {
31 if (b == 0) return a;
32 else return gcd(b, a % b);
33 }
34
35 int e_gcd(int a, int b, int& x, int& y) {
36 if (b == 0) {
37 x = 1;
38 y = 0;
39 return a;
40 }
41 else {
42 int ans = e_gcd(b, a % b, x, y);
43 int temp = x;
44 x = y;
45 y = temp - (a / b) * y;
46 return ans;
47 }
48 }
49
50 int main() {
51 int a, b;
52 while (cin >> a >> b) {
53 int x, y;
54 int d1, d2;
55 d1 = gcd(a, b);
56 d2 = e_gcd(a, b, x, y);
57 printf("%d %d %d %d\n", d1, d2, x, y);
58 }
59 _getch();
60 return 0;
61 }
1 //***********************************************************************************************
2 /*
3 欧几里得算法也称辗转相除法,如果要求a,b的最大公约数,则gcd(a, b) = gcd(b, a % b),
4 直到a % b = 0,此时b就是要求的最大公约数。
5 扩展欧几里得算法是在求最大公约数的基础上求出一组x,y使得x*a + y*b = gcd(a, b)。
6 这个方程是有多解的,以下算法所求的是满足|x|+|y|最小的一组x0,y0。可以以此x0,y0表示方程
7 的通解:
8 x = x0 + (b / a) * t
9 y = y0 - (a / b) * t
10 现在我们需要求x,y使之满足a*x + b*y = gcd(a, b)。已知它的下一个状态是b*x1 + a%b*y1 = gcd(a, b)。
11 而a%b可以写成a - (a / b) * b(a/b为指的是整除)。可推得:
12 gcd(b, a % b) = b * x1 + (a - (a / b) * b) * y1
13 = a * y1 + b * (x1 - (a / b) * y1)
14 gcd(a, b) = a * x + b * y
15 所以:
16 x = y1;
17 y = x1 - (a / b) * y1
18 在最终状态时, a = gcd, b = 0。此时就领x = 1, y = 0。(y可以是任何值,等于0时求出来的特解就是
19 |x| + |y|最小的解)。
20 */
21 //************************************************************************************************
22
23 #include<iostream>
24 #include<cstdio>
25 #include<cstdlib>
26 #include<conio.h>
27
28 using namespace std;
29
30 int gcd(int a, int b) {
31 if (b == 0) return a;
32 else return gcd(b, a % b);
33 }
34
35 int e_gcd(int a, int b, int& x, int& y) {
36 if (b == 0) {
37 x = 1;
38 y = 0;
39 return a;
40 }
41 else {
42 int ans = e_gcd(b, a % b, x, y);
43 int temp = x;
44 x = y;
45 y = temp - (a / b) * y;
46 return ans;
47 }
48 }
49
50 int main() {
51 int a, b;
52 while (cin >> a >> b) {
53 int x, y;
54 int d1, d2;
55 d1 = gcd(a, b);
56 d2 = e_gcd(a, b, x, y);
57 printf("%d %d %d %d\n", d1, d2, x, y);
58 }
59 _getch();
60 return 0;
61 }