一,相关概念
最大公约数:两个数公约数中最大的一个
最小公倍数:两个数公倍数中最小的一个
例如:12 18
公约数有:1 2 3 6
则最大公约数为6
公倍数:36 72 108.......
则最小公倍数为36
二,代码实现
1. 常规解法
思路:利用for循环累加i的值,求出两个数的最大公约数、最小公倍数。
#include<stdio.h>
int main()
{
int a=0,b=0;
scanf("%d %d",&a,&b);
int i=1,m=0,n=0;
for(i=1; i<a && i<b; i++)
{
if( a%i==0 && b%i==0)
{
m=i;
}
}
n=m*(a/m)*(b/m);
printf("%d\n%d",m,n);
return 0;
}
2. 短除法
短除法,也叫倒除法,我们进行进制转换时也会用到这种方法。
假设我们输入 m=12,n=18 ,初始化最大公约数 gcd=1
我们发现 2 是12和18的一个公因子,我们令 m /= 2 ,n /= 2 ,gcd *= 2 ,
现在 m == 6 , n == 9 , gcd == 2
又发现 3 是 6 和 9 的一个公因子,我们令 m /= 3 , n /= 3 , gcd *= 3
现在m == 2 , n == 3 , gcd == 6
我们找不到除 1 以外的 2 和 3 的公因子了
所以现在的 gcd == 6 就是我们要找的最大公因数
而最小公倍数 lcm = gcd * m * n = 6 * 2 * 3 = 36
#include <stdio.h>
int main() {
int m, n;
scanf("%d %d", &m, &n);
int gcd = 1;
for (int i = 2; i <= m && i <= n; i++) {
while (m % i == 0 && n % i == 0) {
m /= i;
n /= i;
gcd *= i;
}
}
printf("%d %d\n", gcd, m * n * gcd);
return 0;
}
但由于短除法效率其实并不理想,时间复杂度可以达到O(n)(当输入质数时)
所以我们一般会用下面的辗转相除法,其时间复杂度为 O(log(n)),代码量少且运算速度快。
3. 辗转相除法
#include <stdio.h>
int gcd(int a, int b) {
return (a % b == 0) ? b : gcd(b, a % b);
}
int main() {
int m, n;
scanf("%d %d", &m, &n);
int ans = gcd(m, n);
printf("%d %d\n", ans, m * n / ans);
return 0;
}