编程之美2.7最大公约数、最小公倍数

it2025-03-01  35

方法一:辗转相除法                                                                                                       点击此处返回总目录

方法二:使用减法操作

方法三:使用位运算和减法操作

 

 

 

最大公约数(greatest common divisor)、最小公倍数(least common multiple)。

1. 求最大公约数有多种方法,常见的有质因数分解法、短除法、辗转相除法、更相减损法。

2. a,b的最大公约数gcd(a,b)与最小公倍数lcm(a,b)的关系是:

    gcd(a,b) *  lcm(a,b) = a*b 

 

 

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

 

【方法】

假设a>b,a除以b余数为c(c!=0)。则 a与b的最大公约数 = b与c的最大公约数。即:

gcd(a,b) = gcd(b,c)

 

比如要求6105和2146的最大公约数。求法如下:

6105=2146×2+1813        6105与2146的最大公约数等于2146与1813的最大公约数 2146=1813×1+333          2146与1813的最大公约数等于1813与333的最大公约数 1813=333×5+148            1813与333的最大公约数等于333与148的最大公约数 333=148×2+37                333月148的最大公约数等于148与37的最大公约数 148=37×4+0                    148月37的最大公约数为37。(除尽)。 因此37为8251与6105的最大公因数。

 

【证明】

我简单的证明一下:

若要求a、b的公约数,不妨设a>b。

假设a = kb+c。即a除以b的余数是c。

1. 如果r是a和b的公约数,则r也是c的约数。

    证明:因为r是a和b的公约数,所以a%r=0,b%r=0。而a%r = (kb+c)%r = c%r = 0。所以r也是c的约数。r是c和b的公约数。

2. 如果t是b和c的公约数,则t也是a的约数。

    证明:因为t是b和c的约数,所以b%t=0, c%t = 0。而a%r = (kb+c)%r = 0。所以,t也是a的约数。t是a和b的公约数。

由1和2得,a和b的公约数也是b和c的公约数,b和c的公约数也是a和b的公约数。因此,a和b的公约数与b和c的公约数是相同的。当然最大公约数也是相同的。所以gcd(a,b) = gcd(b, a%b)

 

【网上更详细的证明】

我把网上的更详细的证明放在下面,有兴趣的可以看一下。没兴趣的就算了,记住方法就行。

 

 

【代码】

 

结果:

 

 

方法二、使用减法代替取余操作

方法一中使用了取余操作。对于大整数而言,取余运算(其中用到除法)是非常昂贵的开销,将成为整个算法的瓶颈。

我们可以用减法操作来代替取余操作。

 

【方法】

假设a>b,a-b=c(c!=0)。则 a与b的最大公约数 = b与c的最大公约数。即:

gcd(a,b) = gcd(a-b,b)

 

比如要求6105和2146的最大公约数。

6105-2146 = 3959    6105与2146的最大公约数等于3959与2146的最大公约数

3959-2146 = 1813    3959与2146的最大公约数等于2146与1813的最大公约数

2146-1813 = 333      2146与1813的最大公约数等于1813与333的最大公约数

1813-333 = 1480      1813与333的最大公约数等于1480与333的最大公约数

1480-333 = 1147       1480与333的最大公约数等于1147与333的最大公约数

1147-333 = 814         1147与333的最大公约数等于814与333的最大公约数

814-333 = 481           814与333的最大公约数等于481与333的最大公约数

481-333 = 148           481与333的最大公约数等于333与148的最大公约数

333-148 = 185           333与148的最大公约数等于185与148的最大公约数

185-148 = 37             185与148的最大公约数等于148与37的最大公约数

148-37 = 111              148与37的最大公约数等于111与37的最大公约数

111-37 = 74                111与37的最大公约数等于74与37的最大公约数

74-37 = 37                  74与37的最大公约数等于37与37的最大公约数

37-37=0                      37与37的最大公约数等于37。

 

【证明】

若要求a、b的公约数,不妨设a>b。

1. 如果r是a和b的公约数,则r也是a-b的约数。

    证明:因为r是a和b的公约数,所以a%r=0,b%r=0。而(a-b)%r = 0。所以r也是a-b的约数。r是a-b和b的公约数。

2. 如果t是a-b和b的公约数,则t也是a的约数。

    证明:因为t是a-b和b的约数,所以(a-b)%t=0, b%t = 0。而a%r = (a-b+b)%r = 0。所以,t也是a的约数。t是a和b的公约数。

由1和2得,a和b的公约数也是a-b和b的公约数,a-b和b的公约数也是a和b的公约数。因此,a和b的公约数与a-b和b的公约数是相同的。当然最大公约数也是相同的。所以gcd(a,b) = gcd(a-b, b)

 

 

【代码】

 

结果:

 

【分析】

虽然不再需要进行大整数的取余运算,转变成了简单的减法运算。但是同样有不足之处,就是迭代的太慢了。如果遇到(100000000,1)这类情况,就相当让人郁闷了。

 

 

 

方法三、使用位运算和减法来求解

 

【原理】

我们使用下列两个公约数的性质进行分析:

1. 对于a和b,如果a = kx, b = ky , 则 gcd(a,b) = k* gcd(x, y)

    比如12 = 2*6 , 18 = 2* 9 , 那么12和18的公约数 = 2*( 6和9的最大公约数)

2. 对于a和b,如果p是素数、p是a的约数并且p不是b的约数,则gcd(a, b) = gcd(a/p, b)

   p是a的约数但是不是b的约数,说明p可以拿掉。比如3是12的约数,但是3不是16的约数,所以gcd(12,16)等于gcd(4,16)。为什么要抢到p是素数呢?因为如果是合数,就不对了。比如6是12的约数,6不是16的约数,但是gcd(12,16)不等于gcd(2,16)。

 

【方法】

根据上面两个性质,我们就可以有以下方法:

若a、b都为偶数,则gcd(a,b) = 2 * gcd(a/2, b/2)                    //利用性质1。把2提出来。

若a为偶数,b为奇数,则gcd(a,b) = gcd(a/2, b)                     //利用性质2。2为素数。

若b为偶数,a为奇数,则gcd(a,b) = gcd(a, b/2)                     //性质2。

若a、b都为奇数,则gcd(a,b) = gcd(a-b, b)                            //方法二的减法操作。

 

 

【代码】

 

结果:

 

 

方法一,快不好。方法二好不快。方法三,又快又好。

 

 

 

 

 

 

 

 

 

 

最新回复(0)