欧几里得算法
在我读过的文献里,称其是“最古老的算法”之一。
欧几里得算法是用来计算两个整数的最大公约数,其算法流程如下。
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
如果我们要来证明这个算法的正确性,通常需要找到一个在反复迭代中不变的量。并且这个不变的量和终止的条件 b = 0 b = 0 b=0能够说明函数所返回的就是 gcd ( a , b ) \gcd(a, b) gcd(a,b)。
找到一个不变的量通常是很困难的,因此我们首先要证明算法迭代有限次数后会终止。分两种情况,假设 a > b a \gt b a>b。
- 如果 b > a 2 b \gt \dfrac{a}{2} b>2a,则 a m o d b = a − b < a 2 a \bmod b = a - b \lt \dfrac{a}{2} amodb=a−b<2a。
- 如果 b < a 2 b \lt \dfrac{a}{2} b<2a,则 a m o d b < b < a 2 a \bmod b \lt b \lt \dfrac{a}{2} amodb<b<2a。
所以算法复杂度为 O ( log max ( a , b ) ) O(\log \max(a, b)) O(logmax(a,b))。
我们记 ⟨ a , b ⟩ = { a x + b y ∣ x , y ∈ Z } \lang a, b \rang = \{ax + by~|~x,y \in \mathbb{Z}\} ⟨a,b⟩={ ax+by ∣ x,y∈Z},如果 ⟨ a , b ⟩ \lang a, b\rang ⟨a,b⟩包含 c c c和 d d d,则 ⟨ c , d ⟩ \lang c, d \rang ⟨c,d⟩为 ⟨ a , b ⟩ \lang a, b \rang ⟨a,b⟩的一个子集。
引理1
gcd ( a , b ) = gcd ( b , a