数据结构与算法分析 - 最大公约数(gcd & extended_gcd)

以下内容均节选自《算法导论》第31章

最大公约数

定义:若:
\[\begin{array}{l}
a = p_1^{e_1}p_2^{e_2} \ldots p_r^{e_r}\\
b = p_1^{f_1}p_2^{f_1} \ldots p_r^{f_r}
\end{array}\]

则:
\[\gcd( a,b) = p_1^{\min ( e_1,f_1)}p_2^{\min ( e_2,f_2)} \cdots p_r^{\min ( e_r,f_r )}\]

GCD递归定理:对任意非负整数a和任意正整数b,
\[\gcd (a,b) = \gcd ( b,a\bmod b )\]

证明:

先证明充分性  

\[\gcd ( a,b)|\gcd ( b,a\bmod bt)\]

如果设

\[d = \gcd( a,b)\]

则   

\[d|a,d|b\]

由取模定义,可以推导出:
\[( a\,\bmod \,bt) = a - qb,q = \lfloor {a/b} \rfloor \]

因为 ( a mod b) 是 a 与 b 的线性组合,所以由等式:
\[d|a\& d|b \Rightarrow d|( {ax + by} )\]

可知
\[d|\gcd ( {a\,\bmod \,b} )\]

因此,因为 d | b 并且 d | ( a mod b ) ,由最大公约数定义可得:d | gcd ( b , a mod b ) ,即:
\[\gcd ( a\,\bmod \,b )|\gcd ( b,a\,\bmod \,b )\]

必要性证明过程与上述过程类似,故略去。

欧几里德算法

通过上述递归定理,我们可以求解最大公约数:

//c++语言表示欧几里德算法
int gcd(int a,int b){
	if(b==0) return a;
	else return gcd(b,a%b);
}

下面来举例说明该算法的运行过程。考虑 gcd (30 , 21) 的计算过程:
\[\gcd ( {30,21} ) = \gcd ( {21,9} ) = \gcd ( 9,3) = \gcd ( {3,0} ) = 3\]

在这个计算过程中,三次递归调用了欧几里德算法。

注:

     默认假设 a>b>0。若b>a>0,则gcd(a,b)会立即调用gcd(b,a).

即如果第一个自变量小于第二个自变量,则gcd算法进行一次递归调用使两自变量兑换,然后继续往下执行。

类似的,如果b=a>0,则过程在进行一次调用后终止,因为 a mod b = 0

欧几里德算法的推广形式

我们推广该算法,使他能计算出满足下列条件的整系数x和y:
\[d = \gcd ( a,bt) = ax + by\]

定理二:

       如果 a 和 b 是不都为 0 的任意整数,则gcd(a,b)是a和b的线性组合集合 { ax + by | x , y 为整数 } 中的最小正元素.

证明

   设 s 是 a 与 b 的线性组合集中的最小正元素,并且存在x,y,使得 s = ax + by 成立。设
\[q = \left\lfloor {a/s} \right\rfloor \]

则有 :
\[a\bmod s = a - qs = a - q( ax + by) = a( 1 - qx) + b( - qy )\]

因此,a mod s 也是a与b的一种线性组合。但由于a mod s 取值范围 [ 0 ,s ) ,所以 a mod s=0,

因为s是满足这样线性组合的最小正整数,故 a mod s 不能取正数只能取 0.

因此有 s | a ,类似的可推得 s | b。

因此 s 是a与b的公约数,所以 gcd( a , b ) >= s .

又因为 gcd( a , b ) 能被 a 与 b 整除,并且 s = ax + by .

所以 gcd( a , b ) | s . 

但由gcd( a , b ) | s 和 s >0 ,可知 gcd( a , b ) <= s .

故 gcd( a , b ) = s ,证毕

扩展欧几里德算法:

int extended_gcd(int a,int b,int x,int y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int r=extended_gcd(b,a%b,x,y);
	
	int tmp=x;
	x=y;
	y=tmp-a/b*y;

	return r;
}

过程详解:

首先,我们需要通过下述公式获得 (d’,x’,y’)
\[d' = \gcd ( b,a\bmod b ) \Rightarrow d' = bx' + ( a\bmod b )y'\]

由于:
\[d = \gcd ( a,b) = d' = \gcd ( b,a\bmod b)\]

为了得到 d=ax+by 中的 x 和 y,我们改写上述等式为:
\[d = d' = bx' + (a - \left\lfloor {a/b} \right\rfloor )y' = ay' + b( x' - \left\lfloor {a/b} \right\rfloor y')\]

因此,当选择:
\[\left\{ \begin{array}{l}
x = y'\\
y = x' - \left\lfloor {a/b} \right\rfloor y'
\end{array} \right.\]

就可以满足等式 d = ax + by .这样就证明了extended_gcd算法的正确性。

posted @ 2014-08-26 22:53  姜楠  阅读(1067)  评论(0)    收藏  举报