2021-10-06

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;
}

运行结果
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值