1、最大公约数&最小公倍数探讨

求解最大公约数和最小公倍数,应该算是很基本的问题了。也正因为这样,第一篇算法类博客就来研究研究它了。

麻雀虽小,五脏俱全。 也能从中学点东西。

下面谈谈我对这问题的认识。

首先,看似是2个不同的问题,其实,就是一个算法。即求最大公约数,因为,通过观察,我们有以下结论。


a,b的最大公约数是m,最小公倍数是n。  则有以下结论:   a*b=m*n。

如4,6 -----   最大公约数2,最下公倍数12   满足4*6 = 2*12.

下面通过公式证明:

假设x=abc, y=bcd,

 则最小公倍数为abcd, 最大公约数为bc

最小公倍数为abcd=最大公约数为bc*x/bc*y/bc =xy/bc。

 也就是说 最小公倍数=两数之积/最大公约数

所以,我们通过求最大公约数就能解决这两个问题了。   下面具体分析如何求解最大公约数。


①辗转相除法(又叫欧几里得算法,是一种求两个正整数的最大公约数的古老有效的算法。)

1.输入两整数a和b。

2.a%b得余数r

3.如果r=0,则b为两数的最大公约数。

4.如果r≠0,则另a=b,b=r,再从第二步执行。

5.直到r=0,此时b为两数的最大公约数。

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. void main()  
  5. {  
  6.     int a, b, r;  
  7.     scanf("%d%d",&a,&b);  
  8.     r = a % b;  
  9.   
  10.     while (r!=0)  
  11.     {  
  12.         a = b;  
  13.         b = r;  
  14.         r = a%b;  
  15.     }  
  16.     printf("%d",b);  
  17. }  
例如,求15,25的最大公约数。

15除25余15------- 25除15余10--------15除10余5-----------10除5余0. 故最大公约数为5.


②更相减损术(我国古代数学专著《九章算术》中介绍的一种求两个最大公约数的算法)

有两整数a和b:

1. 若a>b,则a=a-b

2. 若a<b,则b=b-a

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

4. 若a≠b,则再回去执行①

5. 直到a=b。此时a即为两数的最大公约数

[cpp]  view plain copy
  1. #include<stdio.h>  
  2. void main ( )  
  3. {  
  4.     int a,b;  
  5.     scanf("%d%d",&a,&b);  
  6.   
  7.     while (a!=b)  
  8.     {  
  9.         if(a>b)  
  10.             a-=b;  
  11.         else  
  12.             b-=a;  
  13.     }  
  14.   
  15.     printf("%d",a);  
  16. }  

求98,63的最大公约数:
98-63=35
63-35=28
35-28=7
28-7=21
21-7=14
14-7=7
所以,98和63的最大公约数等于7。

③穷举法

1. 首先对数据m和n判断大小,小的赋值给smaller,大的赋值给larger

2. index索引从2开始到smaller遍历,发现有没有数据可以同时被两者整除,有则更新数据

3. 循环结束后,获取最大的公约数

[cpp]  view plain copy
  1. int GetMaxCommonDivide(int n, int m)    
  2. {    
  3.     int index;    
  4.     int smaller;    
  5.     int larger;    
  6.     int value;    
  7.     assert(n && m);    
  8.     
  9.     if(n > m){    
  10.         larger = n;    
  11.         smaller = m;    
  12.     }else{    
  13.         larger = m;    
  14.         smaller = n;    
  15.     }    
  16.     
  17.     value = 1;    
  18.     for(index = 2; index <= smaller; index++){    
  19.         if(0 == (smaller % index) && 0 == (larger % index))    
  20.             value = index;    
  21.     }    
  22.     
  23.     return value;    
  24. }   
比如4,6

首先  smaller=4,larger=6。  index=2,  smaller%index==0 并且 larger%index==0, 故最大公约数为index=2.

 
到此,常见的,较好的3种算法都已经介绍好了。在实际应用中,我们的选择,还是视情况而定。下面做个小小的比较。

更相减损术和辗转相除法的主要区别在于前者所使用的运算是“减”,后者是“除”。从算法思想上看,两者并没有本质上的区别,但是在计算过程中,如果遇到一个数很大,另一个数比较小的情况,可能要进行很多次减法才能达到一次除法的效果,从而使得算法的时间复杂度退化为O(N),其中N是原先的两个数中较大的一个。相比之下,辗转相除法的时间复杂度稳定于O(logN)。

算法一说,各有各的好处,各有各的使用对象。希望,在充分掌握这三种方法的基础上,加以选择。


下面补充一个多数最大公约数的算法。  原理类似,利用辗转相除法。

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. void main()  
  5. {  
  6.     int a, b, i, r, n;  
  7.   
  8.     scanf("%d",&n);   // 数的个数  
  9.     scanf("%d",&b);  
  10.   
  11.     for (i=0;i<n-1;i++)  
  12.     {  
  13.         scanf("%d",&a);  
  14.         r = a % b;  
  15.   
  16.         while (r!=0)  
  17.         {  
  18.             a = b;  
  19.             b = r;  
  20.             r = a%b;  
  21.         }  
  22.     }  
  23.   
  24.     printf("%d",b);  
  25. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值