以下内容均节选自《算法导论》第31章
最大公约数
定义:若:
[egin{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,amod b )]证明:
先证明充分性
[gcd ( a,b)|gcd ( b,amod bt)]
如果设
[d = gcd( a,b)]
则
[d|a,d|b]
由取模定义,可以推导出:
[( a\,mod \,bt) = a - qb,q = lfloor {a/b} floor ]因为 ( a mod b) 是 a 与 b 的线性组合,所以由等式:
[d|a& d|b Rightarrow d|( {ax + by} )]可知
[d|gcd ( {a\,mod \,b} )]因此,因为 d | b 并且 d | ( a mod b ) ,由最大公约数定义可得:d | gcd ( b , a mod b ) ,即:
[gcd ( a\,mod \,b )|gcd ( b,a\,mod \,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 = leftlfloor {a/s} ight floor ]则有 :
[amod 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,amod b ) Rightarrow d' = bx' + ( amod b )y']由于:
[d = gcd ( a,b) = d' = gcd ( b,amod b)]为了得到 d=ax+by 中的 x 和 y,我们改写上述等式为:
[d = d' = bx' + (a - leftlfloor {a/b} ight floor )y' = ay' + b( x' - leftlfloor {a/b} ight floor y')]因此,当选择:
[left{ egin{array}{l}
x = y'\
y = x' - leftlfloor {a/b} ight floor y'
end{array} ight.]就可以满足等式 d = ax + by .这样就证明了extended_gcd算法的正确性。