1、给出Bezout定理的完整证明。
证明:
我们不妨构造一个集合
S
=
{
a
x
+
b
y
:
x
,
y
∈
Z
且
a
x
+
b
y
>
0
}
S = \{ ax + by:x,y \in \Z 且 ax+by > 0 \}
S={ax+by:x,y∈Z且ax+by>0}由良序定理,我们可以得到该非空集合 S 中必然有一个最小数
d
=
a
r
+
b
s
,
r
,
s
∈
Z
d = ar + bs, r,s \in \Z
d=ar+bs,r,s∈Z。我们认为它是 a 和 b 最大公因子,以下我们做出证明。
令 a = dq + r0,0<= r0 < d 那么有 r0 = a - dq。将 d = ar + bs 代入我们可以得到
r
0
=
a
−
(
a
r
+
b
s
)
q
=
a
−
a
r
q
−
b
s
q
=
a
(
1
−
r
q
)
+
b
(
−
s
q
)
r0 = a - (ar+bs)q=a-arq - bsq=a(1-rq)+b(-sq)
r0=a−(ar+bs)q=a−arq−bsq=a(1−rq)+b(−sq)我们不难看出 r0 也在集合 S 之中。如果 r0 > 0,那么这和 d 是 S 中的最小值相矛盾,所以 r0 只能是0,即 a = dq+0,d 整除 a。同理可得 d 也整除 b。故 d 是 a 和 b 的公因子。
接下来我们证 d 是 a 和 b 的最大公因子。
假设存在 d0 同时整除 a 和 b,那么我们可以得到 a = q * d0, b =k * d0
则 ar + bs = q * d0r + k * d0s = d0 (qr + ks) = d
我们可以得到 d0 整除 d。
由上面的一系列证明我们可以得到存在一对整数 r,s 使得 gcd(a, b) = ar + bs。
2、实现GCD算法的迭代版本。
//函数:求整数 a 和 b 的最大公因数 gcd。
//输入:两个 int 类型的数据 a, b,且 a > b。
//输出:a 和 b 的最大公因子。
int gcd(int a, int b) {
if (b == 0) return a;
int t_a = 0;
while (b) {
t_a = a;
a = b;
b = t_a % b;
}
return a;
}
3、实现EGCD算法。输入:a、b两个整数,输出:r、s、d三个整数,满足ar + bs =d。
//输入:int 类型的数据 a, b 以及 int 类型指针 r, s。且 a > b,*r 和 *s 的初始值分别为 1 和 0。
//输出:a 和 b 的最大公因数 gcd,而且修改 *r, *s 的值为 a 和 b 的贝祖系数。
int egcd(int a, int b, int *r, int *s){
if(b == 0) return a;
int r0 = 1, s0 = 0, r1 = 0, s1 = 1;
int q = 0, rest = 0;
int t_r0,t_s0;
while(b){
q = a/b, rest = a%b;
t_r0 = r0, t_s0 = s0;
a = b, r0 = r1, s0 = s1;
b = rest, r1 = t_r0 - q*r1, s1 = t_s0- q*s1;
}
*r = r0, *s = s0;
return a;
}
4、实现一种批处理版本的GCD算法,即,给定一个整数数组,输出其中所有整数的最大公因子。输入:一个整数数组a;输出:一个整数d,是a数组中所有整数的最大公因子。
//函数:求一组整数集 a 中所有整数的最大公因子
//输入:整型数组 a , 数组 a 的长度 len
//输出:整数集a 中所有整数的最大公因子
//gcd函数参照第 2 题中的 gcd() 函数
int s_gcd(int *a, int len) {
if (len == 1) return a[0];
int ans = gcd(a[0], s_gcd(a + 1, len - 1));
return ans;
}