Practice yourself, for heaven's sake, in little things;
and thence proceed to greater.
看在上帝的份上,先从小事做起吧;
而后才能做更大的事。
目录
1.欧几里得算法又称辗转相除法,是指用于计算两个非负整数a,b的最大公约数。
古希腊数学家欧几里得在其著作《The Elements》中最早描述了这种算法,所以被命名为欧几里得算法。
2.假设需要求 1997 和 615 两个正整数的最大公约数,用欧几里得算法,是这样进行的:
(1)1997 / 615 = 3(余152)
(2)615 / 152 = 4(余7)
(3)152 / 7 = 21(余5)
(4)7 / 5 = 1 (余2)
(5)5 / 2 = 2 (余1)
(6)2 / 1 = 2 (余0)
至此,最大公约数为1
3.用除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数,所以就得出了 1997 和 615 的最大公约数 1。
算法E(欧几里得算法)给定两个正整数 n 和 m,求它们的最大公约数,即能够同时被 n 和 m 整除的最大正整数。
E1.【确保 n > m】如果 n < m,交换 n、m 的值;
E2.【求余数】用 n 除以 m 并将余数设为 r;( r 的取值范围为:0 <= r < m)
E3.【余数为 0?】若 r = 0,算法结束,m 就是最大公约数;
E4.【减少】置 n = m,m = r,并返回步骤 E1。
#include <stdio.h>
int gcd(int n, int m) {
int r = n % m;
while (r != 0) {
n = m;
m = r;
}
return m;
}
int main() {
int n, m, ret;
printf("请输入两个正整数:");
scanf("%d %d", &n, &m);
if(n < m){
ret = gcd(m, n);
}
else {
ret = gcd(n, m);
}
printf("%d 和 %d 的最大公约数为:%d", n, m, ret);
return 0;
}
为了提高效率,改变算法E,使得像 n = m 这样平凡的替代运算都加以避免,以算法E的风格来写出这个新算法,称为算法F。
算法F(提高效率的欧几里得算法)给定两个正整数 n 和 m,求它们的最大公约数,即能够同时被 n 和 m 整除的最大正整数。
F1.【求余数】用 n 除以 m 并让 n 等于所得到的余数;
F2.【余数为零?】若 n = 0,算法结束,n 就是所求的最大公约数;
F3.【求余数】用 m 除以 n 并让 m 等于所得到的余数;
F4.【余数为零?】若 m = 0,算法结束,m 就是所求的最大公约数。
#include <stdio.h>
int gcd(int n, int m) {
int flag;
while (1) {
n %= m;
if (!n) {
flag = 1;
break;
}
m %= n;
if (!m) {
flag = 0;
break;
}
}
return flag == 1 ? m : n;
}
int main() {
int n, m, ret;
printf("请输入两个正整数:");
scanf("%d %d", &n, &m);
if (n < m) {
ret = gcd(m, n);
}
else {
ret = gcd(n, m);
}
printf("%d 和 %d 的最大公约数是:%d", n, m, ret);
return 0;
}
算法G(扩充的欧几里得算法)给定两个正整数 n 和 m,求它们的最大公约数 d 和两个整数 a 和 b,使得 an + bm = d。
G1.【初始化】置 a' = 1,b = 1,a = 0,b' = 0,c = n,d = m;
G2.【除】设 q 和 r 分别是 c 除以 d 的商和余数;(显然:c = qd + r,且 0 <= r < d)
G3.【余数为零?】如果 r = 0,算法终止,这时,我们如愿得到 an + bm = d;
G4.【循环】置 c = d,d = r,t = a',a' = a,a = t - qa,t = b',b' = b,b = t - qb,并返回 E2。
#include<stdio.h>
int exgcd(int n, int m)
{
int a, a1, b, b1, c, d;
int q, r;
int t;
a1 = b = 1;
a = b1 = 0;
c = n;
d = m;
r = c % d;
q = (c - r) / d;
while (r) {
c = d;
d = r;
t = a1;
a1 = a;
a = t - q * a;
t = b1;
b1 = b;
b = t - q * b;
r = c % d;
q = (c - r) / d;
if (r == 0)
break;
}
return d;
}
int main()
{
int n, m;
int ret;
printf("请输入两个正整数:");
scanf("%d %d", &n, &m);
ret = exgcd(n, m);
printf("符合条件的数字是:%d", ret);
return 0;
}