习题4-7 最大公约数和最小公倍数 (15分)
本题要求两个给定正整数的最大公约数和最小公倍数。
输入格式:
输入在一行中给出两个正整数M和N(≤1000)。
输出格式:
在一行中顺序输出M和N的最大公约数和最小公倍数,两数字间以1空格分隔。
输入样例:
511 292
输出样例:
73 2044
解题思路
最大公约数:指两个或多个整数共有约数中最大的一个。
最小公倍数:两个或多个整数公有的倍数叫做它们的公倍数,其中除0以外最小的一个公倍数就叫做这几个整数的最小公倍数。
我一共尝试了3种方式,如下:
1、枚举法
高中数学(好像是高中?或者初中?)曾经讲过两个方法,辗转相除法和更相减损术。但是可能记不得这两个方法了,比如说我自己。那就只能直接粗暴根据定义解题,取个学术书面的名字就是枚举法,这里也介绍下枚举法。
枚举法:在进行归纳推理时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这结论是可靠的,这种归纳方法叫做枚举法.枚举法是利用计算机运算速度快、精确度高的特点,对要解决问题的所有可能情况,一个不漏地进行检验,从中找出符合要求的答案。
特点:
1、得到的结果肯定是正确的;
2、可能做了很多的无用功,浪费了宝贵的时间,效率低下。
3、通常会涉及到求极值(如最大,最小,最重等)。
4、数据量大的话,可能会造成时间崩溃。
知道了枚举,这道题的解题步骤如下:
最大公约数:计算两个数中的较小数M的公约数,从大到小循环,得到的第一个公约数即为最大公约数。
最小公倍数:两个数中任意一个数M的n倍能够被另一个数N整除,即最小公倍数为M*n;
#include<stdio.h>
int main()
{
int M,N,i,n=1;
scanf("%d %d",&M,&N);
if(M<N)
i=M;
else
i=N;
for(i;i>=1;i--)
{
if(M%i==0&&N%i==0)
{
printf("%d ",i);
break;
}
}
while(1)
{
if(n*M%N==0)
{
printf("%d",n*M);
break;
}
n++;
}
return 0;
}
但是这种方法并不是最优的,效率不高,所以我又去查阅了更相减损术和辗转相除法求最大公约数,如下:
更相减损术算法:
1、任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行步骤2。
2、以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。则步骤1中约掉的若干个2与步骤2中等数的乘积就是所求的最大公约数。
#include<stdio.h>
#include<math.h>
int main()
{
int M,N,n,temp,re;
scanf("%d %d",&M,&N);
while(M%2==0&&N%2==0){
M/=2;
N/=2;
n++;
}
if(M<N){
temp=M;
M=N;
N=temp;
}
while(1){
re=M-N;
if(re==N)
break;
M=(re>N)?re:N;
N=(re>N)?N:re;
}
printf("%d",(int)pow(2,n)*N);
return 0;
}
辗转相除法
用较大数M除以较小数N,再将出现的余数re(第一余数)作为除数与N相除,再用出现的余数(第二余数)和第一余数相除,第一余数为为被除数,如此反复,直到最后余数是0为止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。
#include<stdio.h>
int main()
{
int M,N,n,temp,re;
scanf("%d %d",&M,&N);
if(M<N){
temp=M;
M=N;
N=temp;
}
re=M%N;
while(1){
M=re;
n=re;
re=N%M;
if(re==0)
break;
N=n;
}
printf("%d",M);
return 0;
}
三种方法都编程实现了,测试可运行,使用debug看变量变化认识更深刻。