1.给出Bezout定理的完整证明
定理 2.2. Bézout 定理
设 a 和 b 为非零整数,存在整数 r 和 s 使得:gcd(a, b) = ar + bs 。而且,a 与 b 的最大公因子是惟一的。称 r 和 s 为 Bézout 系数。
证明如下:
构造集合 S = {am − bn : m, n ∈ Z 且 am + bn ≥ 0}.
-
显然,集合 S 非空,根据良序原理,取其中最小值 d = ar + bs,其中 r, s ∈ Z。其中 d 是 a 与 b 的最大公因子。
根据除法算法,a = dq + r0 ,且0 ≤ r0 ≤ d。将 d = ar + bs 代入 r0 = a - dq 中有:r0 = a - (ar + bs) q = a(1 - rq) + b(-sq)。
可见 r0 也符合 d = ar + bs 。因此 r0 也在集合 S 中,如果 r0 >0 时, d 为 S 中最小值,而 0 ≤ r0 ≤ d ,两者相悖,故 r0 = 0,则 a = dq + 0,同理有 d | b;可得 d 是 a,b 的公因子。
-
假设存在 d0 同时整除 a 和 b,那么我们可以得到 a = q * d0, b =p* d0
则 d = ar + bs = q * d0 * r + k * d0 * s = d0 (qr + ps)
我们可以得到 d0 | d。
根据上述内容,可以证出 Bézout 定理。
2.实现GCD算法的迭代版本
int gcd(int a, int b) {
if (b == 0) return a;
int x;
while (b) {
x = b;
b = a % b;
a = x;
}
return a;
}
3.实现EGCD算法。输入:a、b两个整数,输出:r、s、d 三个整数,满足 ar + bs = d
int* egcd(int a, int b){
if (a < b){
int temp = a;
a = b;
b = temp;
}
int arr[3] = {0};
int temp_r, temp_b, temp_ab, n, r0=1, r1=0, b0=0, b1=1;//n用来计算要减的倍数
while (b != 0){
n = a / b;
//实现a和b交换
a %= b;
temp_ab = a;
a = b;
b = temp_ab;
//实现系数交换
r0 -= n * r1, b0 -= n * b1;
temp_r = r0, temp_b = b0;
r0 = r1, b0 = b1;
r1 = temp_r, b1 = temp_b;
}
arr[0] = r0, arr[1] = b0, arr[2] = a;//此时输出的a即为d
return arr;
}
int main(){
int a, b;
cin >> a >> b;
cout << "系数r:" <<egcd(a,b)[0]<< " " << "系数s:" << egcd(a, b)[1]<< " "
<< "最大公因子d:" << egcd(a, b)[2]<< endl;
return 0;
}
4、实现一种批处理版本的GCD算法,即,给定一个整数数组,输出其中所有整数的最大公因子。输入:一个整数数组a;输出:一个整数d,是a数组中所有整数的最大公因子。
int mul_gcd(int arr[],int n){
int d;
if (arr[0] < arr[1]){
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
while (arr[1] != 0){
arr[0] = arr[0] % arr[1];
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
d = arr[0];
for (int i = 2; i < n; i++){
if (d < arr[i]){
int tmp = arr[i];
arr[i] = d;
d = tmp;
}
while (arr[i] != 0){
d = d % arr[i];
int tmp = d;
d = arr[i];
arr[i] = tmp;
}
}
return d;