解题思路:
很多人都用辗转相除法来递归,但是我们上中学时用的更多的应该是短除法,或者叫倒除法,我们进行进制转换时也会用到这种方法
所以我想利用短除法写出代码来表示,也是给大家提供一种不同的思考方式
那么什么是短除法:
假设我们输入 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分
259 人评分
循环如果从1开始程序将无法运行,请问这是为什么,求解大佬解答。
祀如西沉 2023-07-23 19:29:42 |
while循环是当表达式为假之前一直循环,如果从1开始,那不管怎么循环,表达式都会一直成立
#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; } 大佬们求指点,这段代码还可以继续优化吗
#include<stdio.h> int main() { int n,m; scanf_s("%d%d", &n, &m); for (int i = (m < n) ? m : n; i >0 ; i--) { if (!(m % i) && !(n % i)) { printf("%d %d", i, m*n/i); break; } } return 0; }
为什么循环语句中除和乘都要在i前加一个等号
Jeopardize 2022-11-05 15:41:55 |
m /= i 的意思是把m/i的值赋给m,比如m /= 2 得到的结果是m= m/2
int main() { int m,n,temp; scanf("%d %d",&m,&n); for(int i = 0;i<=m;i++) { if(m % i == 0 && n % i == 0) { temp = i; } } printf("%d %d",temp,m * n /temp); } 这个为什么是错的?
C语言程序设计教程(第三版)课后习题8.5 (C语言代码)浏览:936 |
2005年春浙江省计算机等级考试二级C 编程题(1) (C语言代码)浏览:582 |
C语言程序设计教程(第三版)课后习题5.4 (C语言代码)浏览:780 |
1113题解浏览:785 |
C语言程序设计教程(第三版)课后习题4.9 (C语言代码)浏览:560 |
sizeof的大作用 (C语言代码)浏览:1450 |
图形输出 (C语言代码)浏览:940 |
C语言程序设计教程(第三版)课后习题9.1 (C语言代码)浏览:562 |
C语言程序设计教程(第三版)课后习题8.3 (C语言代码)浏览:383 |
母牛的故事 (C语言代码)浏览:478 |
streng 2023-11-30 14:50:48 |
题目说的就是正整数