CINTA作业二 GCD与EGCD
1、给出Bezout定理的完整证明。
证明:
构造集合 S S S={a ∗ * ∗m+b ∗ * ∗n : m、n ∈ \in ∈Z,且a ∗ * ∗m+b ∗ * ∗n$\ge$0}.
显然集合非空。由良序原则,存在一个自然数最小元d,且d=a ∗ * ∗m+b ∗ * ∗n.
然后证明两个属性: d 是 a 和 b 的公因子;如果存在 a 和 b 的公因子 d‘ ,则 d’ Id .这样就证明了 d = gcd(a , b).
反证法证明: d 是 a 和 b 的公因子.
假设d不能整除a,由除法定理有:
a=q ∗ * ∗d+r,且0 ≤ \le ≤r<d.
而r=a-q ∗ * ∗d=a-q ∗ * ∗(a ∗ * ∗m+b ∗ * ∗n)=(1-q ∗ * ∗m) ∗ * ∗a+(-q ∗ * ∗n) ∗ * ∗b ∈ \in ∈ S S S,
则在集合 S S S中,存在r<d,与d为最小自然数矛盾,所以d|a.
同理可证d|b.
所以 d 是 a 和 b 的公因子.
取 a 和 b 的公因子任意一个公因子 d‘,所以存在d‘|a,d’|b,
即,a=q 1 _1 1 ∗ * ∗d’,b=q 2 _2 2 ∗ * ∗d’。
所以,d=a ∗ * ∗m+b ∗ * ∗n=q 1 _1 1 ∗ * ∗d’ ∗ * ∗m+q 2 _2 2 ∗ * ∗d’ ∗ * ∗n=(q 1 _1 1 ∗ * ∗m+q 2 _2 2 ∗ * ∗n) ∗ * ∗d’,
即,d’ Id
综上所述, d = gcd(a , b)=a ∗ * ∗m+b ∗ * ∗n,Bezout定理证得.
2、GCD算法的迭代版本
int gcd(int a,int b)
{
int temp;
while(b)
{
temp = a%b;
a = b;
b = temp;
}
return a;
}
3、实现EGCD算法
输入:a、b两个整数,输出:r、s、d三个整数满足a ∗ * ∗r+b ∗ * ∗s=d。
#include <iostream>
using namespace std;
int* egcd(int a, int b)
{
int r_0 = 1, s_0 = 0, r_1 = 0, s_1 = 1, q, temp;
if (a < b)
{
int temp = a;
a = b;
b = temp;
}
while (b)
{
q = a / b;
temp = a % b;
a = b;
b = temp;
temp = r_0 - q * r_1;
r_0 = r_1;
r_1 = temp;
temp = s_0 - q * s_1;
s_0 = s_1;
s_1 = temp;
}
int n[3];
n[0] = r_0;
n[1] = s_0;
n[2] = a;
return n;
}
int main()
{
int a, b;
cout << "请输入两个整数:" << endl;
cin >> a >> b;
cout << "系数r:" << egcd(a, b)[0] << endl;
cout << "系数s:" << egcd(a, b)[1] << endl;
cout << "最大公因子d:" << egcd(a, b)[2] << endl;
cout << a << "*" << egcd(a, b)[0] << " + " << b << "*" << egcd(a, b)[1] << " = " << egcd(a, b)[2] << endl;
}
4、实现一种批量处理版本的GCD算法,即,给定一个整数数组,输出其中所有整数的最大公因子。输入:一个整数数组a;输出一个整数d,是a数组中所有整数的最大公因子。
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
int temp;
while(b)
{
temp = a%b;
a = b;
b = temp;
}
return a;
}
int bat_gcd(int a[], int len)
{
int temp = a[0];
for(int i = 1; i < len; i++)
{
temp = gcd(temp,a[i]);
}
return temp;
}
int main()
{
int a[6] = {63,21,49,42,56,35};
int len = sizeof(a)/sizeof(int);
cout << bat_gcd(a,len) << endl;
return 0;
}