【算法】求最大公约数和最小公倍数(辗转相除法)

备注

2019/7/30 星期二
高中数学必修三学习了“算法初步”,其中有一个叫做辗转相除的算法,这是一个神奇的算法,可以用来求两正整数的最大公约数。这种算法可以避免枚举每一个数的约数,从而减小运算量。不仅在程序设计中,平时的日常生活也可以用这种方式来计算公约数。

一、辗转相除法求最大公约数

1. 功能介绍

求正整数的最大公约数

2. 原理

两数中较大数a和较小数b的最大公约数与两数差a-b和b的最大公约数相同,由此我们可以考虑用较大数除以较小数,求得商和余数,不断重复,最终的除数即为所要求得最大公约数。由除法的性质可知,该方法一定能在有限步数后求得最大公约数。

最近无意之中看到了一个关于辗转相除法原理的图形化解释。十分形象,所谓两个数字的最大公约数问题可以被看成是在一个长为a宽为b的长方形里找能完全平铺的最大正方形的边长。而这个过程就好像我们无聊时在纸上玩的游戏一样,不断用较小边做最大正方形去逼近这个长方形,直到有一个小正方形的正好可以填满空位,而这个小正方形的边长恰巧就是a,b的最大公约数。虽然有点神奇,但这就是数学的魅力图1

3. 例如

82516105的最大公约数:

  1. 8251 = 6105 × \times × 1 + 2146
  2. 6105 = 2146 × \times × 2 + 1813
  3. 2146 = 1813 × \times × 1 + 333
  4. 1813 = 333 × \times × 5 + 148
  5. 333 = 148 × \times × 2 + 37
  6. 148 = 37 × \times × 4
  7. 37即为82516105的最大公约数

4. 算法分析

重复使用较大数除以较小数,直到整除,此时的除数就是最大公约数。

5. 算法实现

int a,b,c=1;
scanf("%d%d",&a,&b);
if(a<b) swap(a,b);
while(c){
    
    
	c=a%b;
	a=b;
	b=c;
}
printf("%d",a);

函数版

int gcd(int a,int b){
    
    
	int c=1;
	if(a<b) swap(a,b);
	while(c){
    
    
		c=a%b;
		a=b;
		b=c;
	}
	return a;
}

6. 时间复杂度

辗转相除法的时间复杂度是a,b两数中较大的数的log,即可看做O(logn)的复杂度。具体推导可自行搜索。

二、最小公倍数

当求出最大公约数为x后,通过a × \times × b ÷ \div ÷ x即可求得最小公倍数。


欢迎在评论区提出你宝贵的意见

猜你喜欢

转载自blog.csdn.net/l1447320229/article/details/97811832