[[TOC]]

问题引入

现有两个整数r0,r1r_0,r_1,如何求两个整数的最大公约数,也就是gcd(r0,r1)gcd(r_0,r_1)?

朴素算法

Euclid算法

在数学界,辗转相除法,又称欧几里得(EuclidEuclid)算法,被认为是世界上最早的算法(公元前300年),该算法用于求两个最大公约数的算法。辗转相除法首次出现于欧几里得的《几何原本》(第VII卷,命题yⅠ和Ⅱ)中,而在中国则可以追溯至东汉出现的《九章算术》。

证明: 设r0=q1r1+r2r_0 = q_1 \cdot r_1 + r_2,其中r0,r1,r2,q1Z,0r2<r0r_0,r_1,_r2,q_1 \in \mathbb{Z},0 \leqslant r_2 < | r_0 |,则gcd(r0,r1)=gcd(r1,r2)gcd(r_0,r_1) = gcd(r_1,r_2),简写成(r0,r1)=(r1,r2)(r_0,r_1) = (r_1,r_2)

我们的思路是证明r0,r1r_0,r_1r1,r2r_1,r_2有相同的公因子.形式语言为

x(xr0xr1)x(xr1xr2) \forall x ( x \mid r_0 \land x \mid r_1) \Leftrightarrow \forall x ( x \mid r_1 \land x \mid r_2)

G(x,y)G(x,y)表示x,yx,y公因子的形成的集合

G(r0,r1)=G(r1,r2) G(r_0,r_1) = G(r_1,r_2)

Proof\mathcal{Proof}

dG(r0,r1)dr0dr1dxr0+yr1dr2前提引入: r2=r0q1r1dr2dr1合取引入: dr1dG(r1,r2)\begin{aligned} d \in G(r_0,r_1) &\Leftrightarrow d \mid r_0 \land d \mid r_1 \\ &\Rightarrow d \mid x\cdot r_0 + y\cdot r_1 &\\ &\Rightarrow d \mid r_2 &\text{前提引入: $r_2 = r_0 - q_1\cdot r_1$} \\ &\Rightarrow d \mid r_2 \land d \mid r_1 &\text{合取引入: $d \mid r_1$} \\ &\Leftrightarrow d \in G(r_1,r_2) \end{aligned}

同理:

dG(r1,r2)dr1dr2dxr1+yr2dr0前提引入: r0=q1r1+r2dr0dr1合取引入: dr1dG(r0,r1)\begin{aligned} d \in G(r_1,r_2) &\Leftrightarrow d \mid r_1 \land d \mid r_2 \\ &\Rightarrow d \mid x\cdot r_1 + y\cdot r_2 &\\ &\Rightarrow d \mid r_0 &\text{前提引入: $r_0 = q_1\cdot r_1 + r_2$} \\ &\Rightarrow d \mid r_0 \land d \mid r_1 &\text{合取引入: $d \mid r_1$} \\ &\Leftrightarrow d \in G(r_0,r_1) \end{aligned}

因为gcd(x,y)=max(G(x,y))gcd(x,y) = max(G(x,y)),且G(r0,r1)=G(r1,r2)G(r_0,r_1) = G(r_1,r_2),显然gcd(r0,r1)=gcd(r1,r2)gcd(r_0,r_1) = gcd(r_1,r_2)

Q.E.D\mathcal{Q.E.D}

那么根据上面的证明,我们得出一个重要的结论

gcd(a,b)=gcd(b,a  %  b)    %表示取余运算 gcd(a,b) = gcd(b, a \; \% \; b) \;\;\%\text{表示取余运算}

如何才能求出gcd(x,y)gcd(x,y)呢?以gcd(44,12)gcd(44,12)为例子

(44,12)=(12,8)44=3×12+8=(8,4)12=8+4=(4,0)8=2×4=44440 \begin{aligned} (44,12) &= (12,8) &44 = 3\times 12+8 \\ &=(8,4) & 12 = 8 + 4 \\ &=(4,0) & 8 = 2\times 4 \\ &= 4 & 4\mid 4 \land 4 \mid 0\\ \end{aligned}

具体的

(ri,ri+1)=ri=qi+1×ri+1+ri+2(ri+1,ri+2) (r_i,r_{i+1}) \xlongequal{ r_i = q_{i+1} \times r_{i+1} + r_{i+2}} (r_{i+1},r_{i+2})

由于r1>r2>r3>0r_1 > r_2 > r_3 > \cdots \leqslant 0,必然存在一个kk使得rk+1=0r_{k+1}=0,那时就求出了gcd(r0,r1)gcd(r_0,r_1)

gcd带余除法(r0,r1)r0=q1r1+r2(r1,r2)r1=q2r2+r3(rk1,rk)rk1=qkrk+0(rk,0)\begin{array}{c|c} gcd & \text{带余除法} \\ \hline \\ (r_0,r_1) & r_0 = q_1 \cdot r_1 + r_2 \\ (r_1,r_2) & r_1 = q_2 \cdot r_2 + r_ 3\\ \vdots & \vdots \\ (r_{k-1},r_{k}) &r_{k-1} = q_k \cdot r_k + 0\\ (r_{k},0) & \end{array}

练习

手动计算几个数学进行练习

模板

int gcd(int a, int b) {
    if( b == 0) return a;
    return gcd(b,a%b);
}