首先对于最大公约数,可以看下wiki上面的简介:
最大公约数(英语:Greatest Common Divisor,简写为G.C.D.;或Highest Common Factor,简写为H.C.F.),指某几个整数共有约数中最大的一个。
求两个整数最大公约数主要的方法:
列举法:各自列出约数,再找出最大的公约数。
素因数分解法:两数各作素因数分解,然后取出共有的项乘起来。
短除法
辗转相除法(扩展版):常使用于直观上不容易判别公约数的场合。
我大致看了一下:
- 列举法会比较笨,而且实现起来需要两个数组去存储对应的两个参数的公约数,然后需要比较两个数组中相同的数字,并且取出相同的数字中最大的那一个。这需要使用到数组,也就不得不涉及指针与引用的知识了。
然而,对于c
中的指针,我真的已经忘记得差不多了,于是就放弃了这种实现方式 - 素因数分解法似乎无法使用程序去表达,遂放弃。
辗转相除法,这里面又包含好几种实现方式。我使用了其中一个我认为最容易理解的方式去实现的。
我们可以用右图来解释最大公约数的概念:[6]设一个长方形的边长为a和b。因为a和b的任何公约数c都可以整除a和b,所以长方形的边都可以等分为长度为c的线段,也就是长方形可以被边长为c的正方形正好填满。而最大公约数g是所有可能的c中最大的一个。例如,一个24 × 60的长方形区域可以分成1 × 1、2 × 2、3 × 3、6 × 6或12 × 12的正方形网格。也就是说,12是24和60的最大公约数。
这里得补充一句,无论a,b 只要有一个是素数,则最大公约数为1。不然上述概念是有bug的。
gcd(a,b)
代码会在最后给出
然后看一下最小公倍数的百度百科简介:
最小公倍数
两个或多个整数公有的倍数叫做它们的公倍数。
两个或多个整数的公倍数里最小的那一个叫做它们的最小公倍数。整数a,b的最小公倍数记为[a,b],同样的,a,b,c的最小公倍数记为[a,b,c],多个整数的最小公倍数也有同样的记号。
与最小公倍数相对应的概念是最大公约数,a,b的最大公约数记为(a,b)。
关于最小公倍数与最大公约数,我们有这样的定理:
(a,b)[a,b]=ab(a,b均为整数)
ps: wiki 上面对于最小公倍数的简介,似乎特别官方,不是很容易理解。于是这里引用百度百科上面的解释。
- 关键是看最后一句:(a,b)[a,b]=ab(a,b均为整数)。也就是说
lcm(a,b) = a*b/gcm(a*b);
这句太重要了,只要求得最大公约数,立马就可以求出最小公倍数了。/捂脸笑/
- 关键是看最后一句:(a,b)[a,b]=ab(a,b均为整数)。也就是说
装逼开始
OK,既然概念理清了,剩下的就是用代码去实现了。
#include <iostream> int add(int a, int b); using namespace std; //3.1 编写函数IsPrime,判断某个大于2的正整数是否为素数。 bool isPrime(int num); //3.2 编写函数gcd与lcm,分别求两个正整数的最大公约数与最小公倍数。 int gcd(int a, int b); int lcm(int a, int b); int main() { int a = 20, b = 170, g, lc; // cout << "a:"; // cin >> a; // cout << "b:"; // cin >> b; g = gcd(a, b); lc = lcm(a, b); cout << "gcd(" << a << "," << b << ") = " << g << endl; cout << "lcm(" << a << "," << b << ") = " << lc << endl; return 0; } /** * 最小公倍数 * > 求法:lcm = (a*b)/gcd(a,b); * from: wiki key:最小公倍数 * @param a * @param b * @return */ int lcm(int a, int b) { int g = gcd(a, b); return a * b / g; } /** * 最大公约数 * > 求法:a*b = c*c*k = d*d*m = ... = z*z*p; c,d,z 中最大的数字即是最大公约数 * from: wiki key:辗转相除法 * @return gcd */ int gcd(int a, int b) { // a*b = square = c*c*k; int square = a * b; int g = 1; if (isPrime(a) || isPrime(b)) { g = 1; } else { for (int i = 1; i <= (a > b ? a : b); ++i) { int k = square / (i * i); if (k * (i * i) == square) { g = i; } } } return g; } bool isPrime(int num) { bool prime = true; for (int i = 2; i <= num / 2; ++i) { if (num % i == 0) { prime = false; } } return prime; } int add(int a, int b) { return a + b; }
控制台输出如下:
gcd(20,170) = 10 lcm(20,170) = 340 Process finished with exit code 0