算法一:欧几里得算法
原理:
gcd (a,b) = gcd(b, a mod b)
c++ 算法表述如下:int gcd(int a, int b) { if (b == 0) return a; else return gcd(b, a%b); }
算法二 : stein 算法(类似)
原理:
从公约数的特点入手: 1. 对于a和b,a = k * a1,b = k * b1 则gcd(a, b) = k * gcd(a1, b1) 2. 如果a = p * a1, 假设p是素数,并且 b%p != 0(即b不能被p整除),那么 gcd(a, b) = gcd (p * a1, b) = gcd(a1, b) 根据以上两点我们可以对欧几里得算法进行改进 最简单的方法是, 我们知道:2是一个素数,同时对于乘以2和除以2的运算可以用移位操作实现,从而避免除法 所以取p = 2: (1) 如果a和b都为偶数,则gcd(a, b) = 2 * gcd(a>>1, b>>1)=(gcd(a>>1, b>>1)) << 1
(2) 如果只有a为偶数,则gcd(a, b) = gcd(a>>1, b)
(3) 如果只有b为偶数,则gcd(a, b) = gcd(a, b>>1)(4) 如果a和b都为奇数,则gcd(a, b) = gcd( abs(a-b), min(a, b))-------------这是stein算法表示 gcd(a, b) = gcd(a, a-b) 由于a-b肯定是偶数,所以下一步就会有个除2的动作
所以时间复杂度是O( log(max(a,b)) )
c++ 代码如下:
inline bool is_even(int i) { return !(i & 1); } int gcd_stein(int a, int b) { if (a < b) return gcd_stein(b, a); if (b == 0) return a; if (is_even(a) && is_even(b)) return (gcd_stein(a>>1, b>>1)) << 1; else if (is_even(a)) return gcd_stein(a>>1, b); else if (is_even(b)) return gcd_stein(a, b>>1); else return gcd_stein(b, a-b); }