三种方法求最大公约数及求n个数的最小公倍数

来源:互联网 发布:怎么在淘宝卖虚拟物品 编辑:程序博客网 时间:2024/05/02 13:45

一、三种方法两个数的最大公约数

(1) 辗转相除法

    辗转相除法求最大公约数是一种常用的求两个数的最大公约数的方法。

方法是:

    以小数除大数,如果能整除,那么小数就是所求的最大公约数。否则就用余数来除除数;再用新除法的余数去除刚才的余数。依此类推,直到一个除法能够整除,这时作为除数的数就是所求的最大公约数。  

    具体过程如下:  输入正整数m和n,保证m不小于n;  如果n≠0,则求r=m%n,然后m=n,n=r;重复此操作直到n=0; 如果n=0,则此时m就是最大公约数(如果最后的除数是1,那么原来的两个数是互质数)若要求这两个数的最小公倍数,其值就是这两数之积除以这两数的最大公约数得到的商。

  例如求1515和600的最大公约数,

  第一次:用600除1515,商2余315;

  第二次:用315除600,商1余285;

  第三次:用285除315,商1余30;

  四次:用30除285,商9余15;

  第五次:用15除30,商2余0.

  1515和600的最大公约数是15.

代码实现如下:

#include<stdio.h>

void main()   /*  辗转相除法求最大公约数 */

{

   int m, n, a, b, t, c;

   printf("请输入两个有效的正整数:\n");

   scanf("%d%d", &a, &b);

   m=a;   

   n=b;

   while(b!=0)  /* 余数不为0,继续相除,直到余数为0 */

   { c=a%b; a=b;  b=c;}

   printf("最大公约数为:%d\n", a);

   printf("最小公倍数为:%d\n", m*n/a);

}

程序运行结果截屏如下图:

 

更相减损法

   《九章算术》是中国古代的数学专著其中的“更相减损术”可以用来求两个数的最大公约数即“可半者半之不可半者副置分母、子之数以少减多更相减损求其等也。以等数约之。”  

 翻译成现代语言如下:

  第一步任意给定两个正整数,判断它们是否都是偶数。若是则用2约简,若不是则执行第二步。

  第二步是以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止,则这个等数就是所求的最大公约数。

  其中所说的“等数”就是最大公约数。求“等数”的办法是“更相减损”法 。

简而言之就是有两整数a和b:

 

① 若a>b,则a=a-b

 

② 若a<b,则b=b-a

 

③ 若a=b,则a(或b)即为两数的最大公约数

 

④ 若a≠b,则再回去运行①

 

比如用更相减损术求98与63的最大公约数。

:由于63不是偶数,把98和63以大数减小数,并辗转相减:

98-63=35

63-35=28

35-28=7

28-7=21

21-7=14

14-7=7

所以,98和63的最大公约数等于7。

代码实现如下:

#include<iostream>

using namespace std;

int main()

{

int a,b,g,l;

int gcd(int a,int b);//gcd为英语最大公约数的首字母缩写

int lcm(int a,int b);//lcm即为最小公倍数的缩写

cout<<"请输入两个有效的数字:"<<endl;

cin>>a>>b;

g=gcd(a,b);

l=lcm(a,b);

cout<<"所求的最大公约数为"<<g<<endl;

cout<<"所求的最小公倍数为"<<l<<endl;

return 0;

}

int gcd(int a,int b)//用更相减损法求最大公约数

{

int c;

while(a!=b) //a, b不相等,大数减小数,直到相等为止

{

if(a>b)

{

c=a-b;

a=c;

}

else

{

c=b-a;

b=c;

}

}

return a;

}

int lcm(int a,int b)//最小公倍数等于两数的积除以两数的最大公约数

{

int g,l;

g=gcd(a,b);

l=a*b/g;

return l;

}

程序运行结果截屏如下图:

 

 

    对于辗转相除法和更相减损法这两种算法都需要用循环结构去实现从运算形式上去分析比较两种方法的异同优劣,个人认为更相减损术时效性可能更好一些,因为减法比除法更易于操作。但是具体怎样还是需要大量的实践验证。

⑶穷举法

    穷举法(也叫枚举法)穷举法求两个正整数的最大公约数的解题步骤:从两个数中较小数开始由大到小列举,直到找到公约数立即中断列举,得到的公约数便是最大公约数

   对两个正整数a,b如果能在区间[a,0]或[b,0]内能找到一个整数temp能同时被a和b所整除,则temp即为最大公约数。

代码实现为:

#include "stdio.h"

int gcd (int a,int b) /*自定义函数求两数的最大公约数*/

 {  

int  temp;          /*定义义整型变量*/   

temp=(a>b)?b:a;    /*条件运算表达式求出两个数中的最小值*/    

while(temp>0)       

{

        if (a%temp==0&&b%temp==0) /*只要找到一个数能同时被a,b所整除,则中止循环*/   

break;          

temp--;      /*如不满足if条件则变量自减,直到能被a,b所整除*/   

}

return (temp); /*返回满足条件的数到主调函数处*/

}

void main()

 {

 int m,n,t;

 printf("请输入两个数字:");  

 scanf("%d%d",&m,&n);

 t=gcd(m,n);

 printf("最大公约数为: %d\n",t);

}

程序运行结果截屏如下图:

 

 二、求n个数最小公倍数的算法

   首先我们要知道,如果有三个正整数a b c,若d是ab的最小公倍数,e是dc的最小公倍数,那么ea b c的最小公倍数。同理,我们可以推出n个数的最小公倍数的求解,而对于最小公倍数的求解过程我们可以使用一个函数LCM来求解,在此之前我们要明最小公倍数是如何求解的。若k是ab的最大公约数,那么ab的最小公倍数为a*b/k。而对于最大公约数的求解上文中我们有三种方法,最简单的我们可以使用辗转相除法来求得。从而我们可以很快的写出来求最小公倍数的算法,接下来就是要利用数组定义所要求的数字集合,利用循环结构遍历一次数组即可求出n个数的最小公倍数,那么问题就迎刃而解了。
代码实现如下:

#include <stdio.h>

int LCM(int x,int y) //求最小公倍数的算法实现

{

  int a,b,c,z;//定义整形变量

  a=x;

  b=y;

  while(y)//辗转相除法求最大公约数的算法

  {

    z=x%y;

    x=y;

    y=z;

  }

 c=a*b/x;//最小公倍数等于数字之积除以它们的最大公约数

 return c;//返回值

}

int main()

{

  int i=0,lcm,m;//lcm为最小公倍数英文单词的缩写,m表示用户想求得几个数字的最小公倍数

  printf("请输入你想求的n个数字的最小公倍数:\n");

  scanf("%d",&m);

  int a[100];//定义数组表示输入的数字

  for(i=0;i<m;i++)//遍历数组

  {

  scanf("%d",&a[i]);

}

 for(i=0;i<m-1;i++)

{

 lcm=LCM(a[i],a[i+1]);//依次求数字的最小公倍数

 a[i+1]=lcm;

}

 printf("您所求的最小公倍数为:%d\n",lcm);

 return 0;

}

程序运行结果截屏如下图:

 

三、作业总结

      通过这次上机作业,我看到自己的很多不足之处,首先基础知识不扎实,对以前所学的知识理解得不够深刻,掌握得不够牢固,这是导致自己不能完全完成任务的主要原因,在这过程中,遇到了各种各样的问题,有的解决了,有的尝试了很多次依然解决不了,这让我有些苦恼,信心也受到了打击;其次是逻辑思维不够严密,缺乏创新能力,总是想着用最简单最低级的语句解决所有问题,不能想到很多其他的更好更有效率的解决办法,过程繁琐,拖泥带水,看起来不简洁明了;最后就是工作效率不高,一下午可能只能解决一两个小问题,耗费大量的精力和时间却只能换来一段中等水平的代码。
     这些问题使我正视了自己,自己还有很多很多需要学习的地方。通过这次上机作业,使我更加地体会到多看专业书的重要性,只有掌握了一定量的专业知识才能得心应手地解决诸多问题,另外,在做任何事都要有耐心,不要一遇到困难就退缩,一碰到难解决的问题就跳过,在学习和工作中要时刻谨记“踏实”二字,踏踏实实认认真真学习基础,它好比通向成功的铺路石,不可或缺。
     但也有好处,在这次作业过程中,体现出了自己设计开发的能力以及综合运用知识的能力,体会了学以致用,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。在今后的学习中,我们应该发现自己的不足然后虚心学习,更加完善自己,为今后步入社会参加工作打下足够的基础,更重要的是,要面对社会的挑战,只有不断的学习、实践,再学习、再实践。这对于我们的将来也有很大的帮助。
      此次作业设计也让我明白了思路即出路,有什么不懂不明白的地方要及时请教或上网查询,只要认真钻研,动脑思考,动手实践,就没有弄不懂的知识,最后,还要衷心感谢老师耐心的指导和答疑,让我们能够更好更快的解决问题,学习到真正有用的知识。谢谢老师!

 

0 0