[[TOC]]
问题引入
现有两个整数r0,r1,如何求两个整数的最大公约数,也就是gcd(r0,r1)?
朴素算法
Euclid算法
在数学界,辗转相除法,又称欧几里得(Euclid)算法,被认为是世界上最早的算法(公元前300年),该算法用于求两个最大公约数的算法。辗转相除法首次出现于欧几里得的《几何原本》(第VII卷,命题yⅠ和Ⅱ)中,而在中国则可以追溯至东汉出现的《九章算术》。
证明: 设r0=q1⋅r1+r2,其中r0,r1,r2,q1∈Z,0⩽r2<∣r0∣,则gcd(r0,r1)=gcd(r1,r2),简写成(r0,r1)=(r1,r2)
我们的思路是证明r0,r1与r1,r2有相同的公因子.形式语言为
∀x(x∣r0∧x∣r1)⇔∀x(x∣r1∧x∣r2)设G(x,y)表示x,y公因子的形成的集合
G(r0,r1)=G(r1,r2)Proof
d∈G(r0,r1)⇔d∣r0∧d∣r1⇒d∣x⋅r0+y⋅r1⇒d∣r2⇒d∣r2∧d∣r1⇔d∈G(r1,r2)前提引入: r2=r0−q1⋅r1合取引入: d∣r1
同理:
d∈G(r1,r2)⇔d∣r1∧d∣r2⇒d∣x⋅r1+y⋅r2⇒d∣r0⇒d∣r0∧d∣r1⇔d∈G(r0,r1)前提引入: r0=q1⋅r1+r2合取引入: d∣r1
因为gcd(x,y)=max(G(x,y)),且G(r0,r1)=G(r1,r2),显然gcd(r0,r1)=gcd(r1,r2)
Q.E.D
那么根据上面的证明,我们得出一个重要的结论
gcd(a,b)=gcd(b,a%b)%表示取余运算如何才能求出gcd(x,y)呢?以gcd(44,12)为例子
(44,12)=(12,8)=(8,4)=(4,0)=444=3×12+812=8+48=2×44∣4∧4∣0具体的
(ri,ri+1)ri=qi+1×ri+1+ri+2(ri+1,ri+2)由于r1>r2>r3>⋯⩽0,必然存在一个k使得rk+1=0,那时就求出了gcd(r0,r1)
gcd(r0,r1)(r1,r2)⋮(rk−1,rk)(rk,0)带余除法r0=q1⋅r1+r2r1=q2⋅r2+r3⋮rk−1=qk⋅rk+0
练习
手动计算几个数学进行练习
模板
int gcd(int a, int b) {
if( b == 0) return a;
return gcd(b,a%b);
}