Euclid 欧几里得算法

问题

求两正整数aabb的最大公约数(GreatestCommonDivisorGreatest Common Divisor)和最小公倍数(LeastCommonMultipleLeast Common Multiple)。

解法

gcd(a,b)gcd(a, b)表示非负整数a,ba, b的最大公约数,任意正整数aabb满足:

gcd(a,b)={bamodb=0gcd(b,amodb)amodb0gcd(a, b) = \begin{cases} b & a \bmod b = 0 \\ gcd(b, a \bmod b) & a \bmod b \neq 0 \end{cases}

也可以写作:

gcd(a,b)={ab=0gcd(b,amodb)b0gcd(a, b) = \begin{cases} a & b = 0 \\ gcd(b, a \bmod b) & b \neq 0 \end{cases}

a<ba \lt b,则第一步实际上会交换两个数字的位置,因为必然有a÷b=0a \div b = 0。每一步得到的余数amodba \bmod b都会越来越小,必然存在一个数字rr使得gcd(r,0)=gcd(a,b)gcd(r, 0) = gcd(a, b)rr即为a,ba, b的最大公约数。

a0,b0a_0, b_0为原始的a,ba, b,用迭代式表达:

a0=a,b0=bgcd(a0,b0)=gcd(b0,a0modb0)=gcd(a1,b1)a1=b0,b1=a0modb0gcd(a1,b1)=gcd(b1,a1modb1)=gcd(a2,b2)a2=b1,b2=a1modb1gcd(a2,b2)=gcd(b2,a2modb2)=gcd(a3,b3)a3=b2,b3=a2modb2gcd(ai,bi)=gcd(bi,aimodbi)=gcd(ai+1,bi+1)ai+1=bi,bi+1=aimodbigcd(an,bn)=gcd(bn,anmodbn)=gcd(an+1,0)an+1=bn,bn+1=0\begin{matrix} a_{0} = a, b_{0} = b \\ gcd(a_{0}, b_{0}) = gcd(b_{0}, a_{0} \bmod b_{0}) = gcd(a_{1}, b_{1}) & \rightarrow & a_{1} = b_{0}, b_{1} = a_{0} \bmod b_{0} \\ gcd(a_{1}, b_{1}) = gcd(b_{1}, a_{1} \bmod b_{1}) = gcd(a_{2}, b_{2}) & \rightarrow & a_{2} = b_{1}, b_{2} = a_{1} \bmod b_{1} \\ gcd(a_{2}, b_{2}) = gcd(b_{2}, a_{2} \bmod b_{2}) = gcd(a_{3}, b_{3}) & \rightarrow & a_{3} = b_{2}, b_{3} = a_{2} \bmod b_{2} \\ \cdots \\ gcd(a_{i}, b_{i}) = gcd(b_{i}, a_{i} \bmod b_{i}) = gcd(a_{i+1}, b_{i+1}) & \rightarrow & a_{i+1} = b_{i}, b_{i+1} = a_{i} \bmod b_{i} \\ \cdots \\ gcd(a_{n}, b_{n}) = gcd(b_{n}, a_{n} \bmod b_{n}) = gcd(a_{n+1}, 0) & \rightarrow & a_{n+1} = b_{n}, b_{n+1} = 0 \\ \end{matrix}

对于第kk步递归,有ak=bk1,bk=ak1modbk1a_{k} = b_{k-1}, b_{k} = a_{k-1} \bmod b_{k-1}。迭代到第n+1n + 1步时得到an+1=bn,bn+1=0a_{n+1} = b_{n}, b_{n+1} = 0an+1,bna_{n+1}, b_{n}即为最大公约数。

欧几里得算法的时间复杂度约为O(log2(max(a,b)))O(log_2 (max(a, b)))

源码

Euclid.h

Euclid.cpp

测试

EuclidTest.cpp

Last updated