求最大公约数的两种方法
在数学计算中经常会碰到计算最大公约数的情况,本文介绍两种最常用的计算方法。这两种方法在CSP等程序设计竞赛中也经常用到。
更相减损术
算法介绍
这种方法出自中国古代的数学专著《九章算术》,《九章算术》作者已不可考,它总结了战国、秦、汉时期的数学成就,主要是用于生产生活的一些实用算术。三国时期,刘徽为本书做了注解,目前流行的就是刘徽注本。
更相减损术原本是用来约分的,因此,也适用于计算最大公约数。原文如下:
可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之。
现代译文:
(对于可以约分的分数来说,)可以折半的话,就折半(即,用2来约分)。如果不可以折半的话,那么就比较分母和分子的大小,用大数减去小数,互相减来减去,一直到减数与差相等为止,用这个相等的数字来约分。
上文中,这个相等的数字\( \times 2^n=\)两数的最大公约数,\(n\)为折半次数。
C++程序
1、递归算法
|
|
此方法的缺点:当a和b的差距较大(如100000
倍)时,会导致错误(递归栈过深)。在C++程序设计中,还可以使用非递归方式来进行计算。
2、非递归算法
|
|
在a和b差距较大时,效率较低。在程序竞赛中,不建议使用此方法。
辗转相除法
在小学生数学竞赛(小学奥数)中,培训机构都是教的这种方法。这种方法效率高,程序时间复杂度低,几乎每种算法书中也都介绍这种方法。下面来记录这种算法,也是给自己做一个备忘录。
辗转相除法也叫欧几里得算法,出自古希腊数学家欧几里得在其著作《The Elements》,所以被命名为欧几里得算法。
算法介绍
假设有两个正整数 \(a\) 和 \(b\)(其中 \(a \)不小于 \(b\)) ,记 \(a\) 除以\(b\)的余数为 \(r\),那么 \(a\) 可以写成这样的形式:$$a=t\times b+r$$其中\(t\)是整数。
假设\(a\)和\( b \)有一个公约数\(u\),则\(a\)和\(b\)都能够被\(u\)整除,即$$a=m\times u$$$$b=n\times u$$其中\(m\)和\(n\)都是整数。
则有$$r=a-t\times b = m\times u-t\times n\times u=(m-tn)\times u$$\(r\)也能被\(u\)整除。
推论
\(a\) 和 \(b\) 的约数的集合,全等于 \(b\) 和 \(r\) 的约数的集合。
\(a\) 和 \(b\) 的最大公约数,就是 \(b\) 和 \(r\) 的最大公约数。
对上述 \(a\) 和 \(b\) 辗转相除,递推为
$$a\div b=t \cdots \cdots r$$
$$b\div r=t_1 \cdots \cdots r_1$$
$$r\div r_1=t_2 \cdots \cdots r_2$$
$$r_1\div r_2=t_3 \cdots \cdots r_3$$
$$\cdots \cdots $$
$$r_{n-3}\div r_{n-2}=t_{n-1} \cdots \cdots r_{n-1}$$
$$r_{n-2}\div r_{n-1}=t_n \cdots \cdots 0$$
此时 \(r_{n−2}\) 和 \(r_{n−1}\)的约数就只有:\(r_{n−1}\) 和 \(r_{n−1}\) 的因数,所以他们的最大公约数就是 \(r_{n−1}\),所以 \(r_{n−1}\)就是 \(a\) 和 \(b\) 的最大公约数。
C++程序
|
|
- 原文作者:图图爸爸
- 原文链接:https://www.tubacode.com/post/gcd.html
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。