解题思路:
很多人都用辗转相除法来递归,但是我们上中学时用的更多的应该是短除法,或者叫倒除法,我们进行进制转换时也会用到这种方法
所以我想利用短除法写出代码来表示,也是给大家提供一种不同的思考方式
那么什么是短除法:
假设我们输入 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;
int j, k;
int lcm, gcd = 1;
scanf("%d %d", &m, &n); //输入m和n
j = m, k = n; //用j和k表示m和n,不破坏m与n的值
if (j > k)
{
j = n, k = m; //确保j是较小的那个
}
for (int i = 2; i <= j; i++) //循环寻找从i到j的因子(注意j是可变的,而i会被重置)
{
if (j % i == 0 && k % i == 0) //判断i是否为j和k的公因子
{
j /= i;
k /= i; //j与k分别除以i
gcd *= i; //gcd乘以i
i = 1; //将i重置为1 (循环末尾会i++)
}
}
lcm = gcd * j * k; //求出最小公倍数lcm
printf("%d %d", gcd, lcm); //输出gcd与lcm
return 0;
}看了评论区的诸多意见,决定重写这份时隔一年的代码:
//短除法求公约公倍
#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))
所以还是建议使用辗转相除法,代码量少且运算速度快:
//辗转相除法求公约公倍
#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;
}0.0分
208 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
#include <stdio.h> int main() { int x,y,m,n,min,max; scanf("%d%d",&x,&y); m=x; n=y; if(x>y) { m=y; n=x; }//确保m小 for(int i=m;i<=m;i--) { if(m%i==0&&n%i==0) { max=i; break;//退出for循环 } } for(int j=1;j<=m;j++) { if(j*m%n==0) { min=j*m; break;//退出for循环 } } printf("%d %d",max,min); return 0; } 哪里错了,一直显示答案错误#include <stdio.h> int main() { int m, n; int b; printf("请输入m,n的值\n"); scanf("%d%d", &m, &n); int a = m * n; if (m > 0 && n > 0) { if (m > n) { b = n; } else { b = m; } } for (; b > 0; b--) { if (m % b == 0 && n % b == 0) { break; } } a /= b; printf("m,n的最大公约数是%d,最小公倍数是%d", b, a); return 0; } 哪儿错了呀qaq#include<stdio.h> int main() { int a,b,c=0; scanf("%d%d",&a,&b); int d=a*b; //辗转相除法,a%b=0--b为最大公约数,a为最小公倍数;c=a%b!=0;a=b;b%c=0;c为最大公约数, while(1) { if(a%b==0) { printf("%d %d",b,d/b); break; } else { c=a%b; a=b; b=c; } } return 0; } 大佬们求指点,这段代码还可以继续优化吗