1、给出Bezout定理的完整证明
构造集合
S
=
{
a
m
+
b
n
:
m
,
n
∈
Z
且
a
m
+
b
n
>
0
}
S= \left\{am+bn:m,n\in\ \mathbb{Z} 且am+bn> 0\right\}
S={am+bn:m,n∈ Z且am+bn>0}
显然集合
S
S
S非空,根据良序原则,
S
S
S中存在最小值
d
d
d,令
d
=
a
r
+
b
s
d=ar+bs
d=ar+bs
以下分两部分证明:
1)证明d是a、b的公因子
由除法定理,设
a
=
d
q
+
r
′
a=dq+r'
a=dq+r′, 且
0
≤
r
′
<
d
。
0\leq r'<d。
0≤r′<d。则有
r
′
=
a
−
d
q
=
a
−
(
a
r
+
b
s
)
q
=
a
(
1
−
r
q
)
+
b
(
−
s
q
)
r'=a-dq=a-(ar+bs)q=a(1-rq)+b(-sq)
r′=a−dq=a−(ar+bs)q=a(1−rq)+b(−sq)
显然,
(
1
−
r
q
)
,
(
−
s
q
)
∈
Z
(1-rq),(-sq)\in\ \mathbb{Z}
(1−rq),(−sq)∈ Z ,且因为
r
′
>
0
r'>0
r′>0 ,则
r
′
∈
S
。
r'\in\ S。
r′∈ S。
又因为
r
′
<
d
r'<d
r′<d,这与
d
d
d是
S
S
S中最小元素相矛盾,因此
r
′
=
0
r'=0
r′=0。
则
d
∣
a
d\mid a
d∣a,同理也可得
d
∣
b
d\mid b
d∣b,故
d
d
d是
a
a
a和
b
b
b的公因子。
2)证明d是所有公因子中最大的
设存在另一个
a
、
b
a、b
a、b的公因子
d
′
d'
d′,则有
a
=
d
′
t
a=d't
a=d′t、
b
=
d
′
k
b=d'k
b=d′k,
t
,
k
∈
Z
t,k\in\ \mathbb{Z}
t,k∈ Z 。
那么
d
=
a
r
+
b
s
=
d
′
t
r
+
d
′
k
s
=
d
′
(
t
r
+
k
s
)
d=ar+bs=d'tr+d'ks=d'(tr+ks)
d=ar+bs=d′tr+d′ks=d′(tr+ks)。
显然,
(
t
r
+
k
s
)
∈
Z
(tr+ks)\in\ \mathbb{Z}
(tr+ks)∈ Z,则
d
′
∣
d
d'\mid d
d′∣d成立,故d是d是所有公因子中最大的。
综上,d=gcd(a,b)成立,又因d=ar+bs,即gcd(a,b)=ar+bs成立
2、实现GCD算法的迭代版本。
//原理:a>=b,有gcd(a,b)=gcd(b,a mod b)
#include<iostream>
using namespace std;
int gcd(int a,int b);
int main()
{
int a,b;
cin>>a>>b;
cout<<a<<"和"<<b<<"的最大公因数是"<<gcd(a,b)<<endl;
}
int gcd(int a,int b)
{
//确保a>b
int temp,r;
if(a<b)
{
temp=b;
b=a;
a=temp;
}
//gcd算法
while(b!=0)
{
r=a%b;
a=b;
b=r;
}
return a;
}
3、实现EGCD算法。输入:a、b两个整数,输出:r、s、d三个整数,满足ar + bs =d。
#include<iostream>
using namespace std;
int egcd(int a,int b,int *r,int *s);
int main()
{
int a,b,r,s;
cin>>a>>b;
cout<<a<<"和"<<b<<"的最大公因数是"<<egcd(a,b,&r,&s)<<endl;
cout<<"bezout系数r="<<r<<" s="<<s<<endl;
}
int egcd(int a,int b,int *r,int *s)
{
//确保a>b
int temp;
if(a<b)
{
temp=b;
b=a;
a=temp;
}
//egcd算法
int r0=1,r1=0,s0=0,s1=1,q,temp0,temp1,temp2;
while(b!=0)
{
//进行等式(矩阵)右边的运算,实际上也就是普通的gcd算法,但是这里还把商q记录了起来,用于计算bezout系数
q=a/b;
temp0=a%b;//必须要有一个容器暂时存放余数,不然没法进行
a=b;
b=temp0;
//根据记录下来的q,完成等式(矩阵)左边的运算,计算计算bezout系数
temp1=r0;
temp2=s0;//必须要有一个容器暂时存放前一个等式的系数,不然没法进行
r0=r1;
s0=s1;
r1=temp1-r1*q;
s1=temp2-s1*q;
}
*r=r0;
*s=s0;
return a;
}
4、实现一种批处理版本的GCD算法,即,给定一个整数数组,输出其中所有整数的最大公因子。输入:一个整数数组a;输出:一个整数d,是a数组中所有整数的最大公因子。
#include<iostream>
using namespace std;
int gcd(int a, int b);
int arr_gcd(int a[], int num);
#define size 10 //数组输入的最大长度
int main()
{
int a[size], cnt=0;
cout << "请输入一个数组:(手动输入EOF表示输入结束)" << endl;
for (int i = 0; i < size; i++)
{
if (!(cin >> a[i]))
{
cnt = i;
break;
}
}
cout << "这些数的最大公因数为:" << arr_gcd(a, cnt) << endl;
}
int arr_gcd(int a[], int num)
{
//由于数组传进来的是一个地址,函数内对数组进行修改的话,原数组也会被改动
//解决方法:先创建一个数组gcd_arr用来拷贝数组a
int gcd_arr [size];
for (int i = 0; i < num; i++)
{
gcd_arr[i] = a[i];
}
for (int i = 0; i < num - 1; i++)
{
gcd_arr[i + 1] = gcd(gcd_arr[i], gcd_arr[i + 1]);
}
return gcd_arr[num - 1];
}
int gcd(int a, int b)
{
//确保a>b
int temp, r;
if (a < b)
{
temp = b;
b = a;
a = temp;
}
//gcd算法
while (b != 0)
{
r = a % b;
a = b;
b = r;
}
return a;
}