解题思路:
很多人都用辗转相除法来递归,但是我们上中学时用的更多的应该是短除法,或者叫倒除法,我们进行进制转换时也会用到这种方法
所以我想利用短除法写出代码来表示,也是给大家提供一种不同的思考方式
那么什么是短除法:
假设我们输入 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分
271 人评分
WU-复数求和 (C++代码)浏览:2119 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:645 |
A+B for Input-Output Practice (V) (C语言代码)浏览:497 |
【偶数求和】 (C语言代码)浏览:460 |
C语言程序设计教程(第三版)课后习题9.3 (C语言代码)浏览:650 |
时间转换 (C语言代码)浏览:697 |
输入输出格式练习 (C语言代码)浏览:773 |
班级人数 (C语言代码)浏览:980 |
C语言程序设计教程(第三版)课后习题8.5 (C语言代码)浏览:710 |
C语言程序设计教程(第三版)课后习题6.9 (C语言代码)浏览:490 |
tiger 2021-02-09 09:57:43 |
感觉短除法容易理解多了,谢谢大佬指点