GCD与EGCD
Bezout定理的证明
证明:Bezout定理
设a和b为非零整数,存在整数r和s使得:
gcd(a,b)=ar+bs
而且,a与b的最大公因子是唯一的。称r和s为Bezout系数
证明:
令 d=gcd(a,b), 则有 d|a、d|b、 d|(a×r+b×s) (r、s∈Z)①
对于a、b的线性组合集合 Y={a×r+b×s:a、b∈
Z
∗
Z^*
Z∗,r、s∈Z},
存在一最小正值(良序原则) t=a×
r
0
r_0
r0+b×
s
0
s_0
s0 (
r
0
r_0
r0、
s
0
s_0
s0∈Z) ②
令q=a/t(取整),p=a mod t =a-qt (0<=p<t) ③
有p=a-q(a×
r
0
r_0
r0+b×
s
0
s_0
s0)=a*(1-q*
r
0
r_0
r0)-b*(q*
s
0
s_0
s0)
p、t均为a、b的线性组合,且由②t为线性组合集合最小元素,③p<t 可知:p=0,因此 t | a !
同理,可证得 t | b 。
d为最大公因子,所以 t | d,又因为① d |(a×r+b×s)即d | t
所以 d=t
所以存在整数r和s使得 d=gcd(a,b)=t=a×
r
0
r_0
r0+b×
s
0
s_0
s0=ar+bs
Bezout定理得证!
【参考:https://www.luogu.com.cn/blog/love-hy/bezout-ding-li-ji-zheng-ming】
实现GCD算法的迭代版本。
代码:
//实现GCD算法的迭代版本
//gcd(a,b)=gcd(b,a mod b)
#include<iostream>
using namespace std;
//mod函数: 计算余数
//input:a、b(a>=b,a、b∈Z*)(输入时a、b不分大小)
//output:r=a mod b(r>=0)
int Mod(int a,int b)
{
int T=0; //两值交换的中转站
int r=0;
if(a<b) { T=a; a=b; b=T; }
r= a%b;
return r;
}
//gcd函数:计算两个整数的最大公因式
//input: a、b (a>=b、a、b∈Z*) (输入时a、b不分大小)
//output:gcd(最大公因式)
int GCD(int a,int b)
{
int Mod(int,int); //函数调用声明
int T=0; //两值交换的中转站
if(a<b) { T=a; a=b; b=T; }
//定义A、B作为GCD计算过程的中间值,C为中转站
int A=0,B=0,C=0;
A=a,B=b;
do
{
C=B; //留住B原来的值给A
B=Mod(A,B);
A=C;
} while(B!=0);
return A;
}
int main()
{
int a=0,b=0;
bool YorN=0;
do
{
cout<<"请输入需要计算最大公因式的两个整数值:";
cin>>a>>b;
cout<<"他们的最大公因式是:"<<GCD(a,b)<<endl;
cout<<"继续计算回复1,退出回复0:";
cin>>YorN;
}while(YorN==1);
return 0;
}
运行结果
实现EGCD算法。输入:a、b两个整数,输出:r、s、d三个整数,满足ar + bs =d。
代码
//实现EGCD算法。输入:a、b两个整数,
//输出:r、s、d三个整数,满足ar + bs =d。
#include<iostream>
using namespace std;
int* EGCD(int a,int b)
{
//两值交换的中转站
int T=0;
if(a<b) { T=a; a=b; b=T; }
//定义指针,用于一次返回三个值
int *R;
//定义数组储存 所求的r、s、d
int RSD[3];
R=RSD;
//定义EGCD计算过程中需要用到的辅助变量
int r1=1,r2=0,s1=0,s2=1,d1=a,d2=b,quotient=a/b;
int t1=0,t2=0,t3=0;//中转值
if(d1-d2*quotient==0)
{
quotient--;
d2=d1-d2*quotient;
r2=r1-r2*quotient;
s2=s1-s2*quotient;
}
else do{
quotient=d1/d2;
t1=d2,t2=r2,t3=s2;
d2=d1-d2*quotient;
r2=r1-r2*quotient;
s2=s1-s2*quotient;
d1=t1,r1=t2,s1=t3;
} while(d2!=0&&d2!=1);
RSD[0]=r2;
RSD[1]=s2;
RSD[2]=d2;
return R;
}
int main()
{
//接收EGCD的返回值
int *rsd;
int a=0,b=0;
bool YorN=0;
do
{
cout<<"请输入要计算的两个整数:";
cin>>a>>b;
rsd=EGCD(a,b);
cout<<"r:"<<rsd[0]<<"\ns:"<<rsd[1]<<"\nd:"<<rsd[2]<<endl;
cout<<"继续计算回复1,退出回复0:";
cin>>YorN;
}while(YorN==1);
return 0;
}
运行结果
实现一种批处理版本的GCD算法,即,给定一个整数数组,输出其中所有整数的最大公因子。输入:一个整数数组a;输出:一个整数d,是a数组中所有整数的最大公因子。
代码
//实现一种批处理版本的GCD算法,
//即,给定一个整数数组,输出其中所有整数的最大公因子。
//输入:一个整数数组a;输出:一个整数d,是a数组中所有整数的最大公因子
//省略前文定义的Mod函数和GCD函数,直接取用
int main()
{
//-------用户输入整数数组-----------
int Lengh; //整数数组长度
cout<<"请输入整数数组的长度:";
cin>>Lengh;
int *P=new int[Lengh];
cout<<"向整数数组逐个输入整数:";
for(int i=0;i<Lengh;i++)
{
cin>>P[i];
}
//--------计算整数数组最大公因式--------
int step=1; //step=Lengh时循环停止
int ToolGCD=GCD(P[0],P[step]);
step++;
do
{
ToolGCD=GCD(ToolGCD,P[step]);
step++;
} while(step<Lengh);
cout<<"整数数组的最大公因数为:"<<ToolGCD<<endl;
delete []P;
return 0;
}
运行结果