欧几里得算法(辗转相除法) 证明及复杂度分析

欧几里得算法核心:

gcd( a , b ) = gcd( b , a%b ) ,其中 gcd 表示 a 和 b 的最大公约数;

证明:

设 a 和 b 的最大公约数为 c ;
则有 c = gcd( a , b ) ;
a = x * c , b = y * c , 其中 x 与 y 互质 (因为 c 是最大公约数)
g = a%b = a - i * b = (x - i * y ) * c , 其中 i = [ a / b ] ,向下取整 ;
又 b = y * c , 且易得 x - i * y 与 y 互质;(下面会证明)
则有 b 与 g 的最大公约数为 c ,
又 g = a%b,
则 gcd( a, b ) = gcd( b , a%b );

接下来,证明 x - i * y 与 y 互质 ,
反证法:
设 x - i * y 与 y 不互质;
则 x - i * y 与 y 存在最大公约数 k ( k>1 ) ;
x - i * y = n * k, y = m * k, 其中 n 和 m 互质;
把 y = m * k, 代入 x 中 得:
x = (n + i * m ) * k
又 y = m * k ,
故 x 与 y 不互质 ,与 上述证明矛盾(前面设x,y是互质的);
所以 x - i * y 与 y 互质 ;

证毕;

gcd( a , b ) = gcd( b , a%b ),求解 a、b 的最大公约数 ,化为 求解b 、a%b 的最大公约数;

符合递归 大问题化成小问题 求解的特性(也可以用循环求解) ;

当前递归到 a%b == 0时(b 整除 a), 即 下一次递归的 b‘ = 0;

下一次递归 的 a’ ,即为当前层 的 b,为最大公约数;

挂代码

int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}

复杂度分析

若 a=b, 那么最大公约数就是b ;
若 a < b , 那么 经过一次操作后 gcd(a ,b) = gcd( b, a%b) = gcd( b , a );
此时, a’ = b, b’ = a % b , a’ > b’ ;

则还是来看 a > b 的情况:

  1. a < 2 * b :
    设 a = 2k (乘号省略),b = k + m (0 第一次操作 变为 gcd( k+m , k-m ) ; // ( a%b = a - i b )
    第二次操作 变为 gcd( k-m, r ) , r = (k+m)%(k-m) < k-m ;
    k-m < k = a/2;
    即两次操作 数据量 最差变为原来的一半,所以复杂度为 O(2logN) ;
  2. a > 2 * b :
    设 a = 2k (乘号省略),b = k - m (0 第一次操作就 变为 gcd (k-m, 2k%(k-m) );
    数据量变为原来一半;
  3. a=2 * b
    最大公约数就是 max( b , 2) ;

综上,最坏时间复杂度 约为 O(2logN) ,去掉常数即为 O(logN) , 底数为 2;

你可能感兴趣的:(数论)