欧几里德算法及扩展

欧几里德算法

        又叫辗转相除法,用于计算两个整数a,b的最大公约数,计算公式 gcd(a,b)=gcd(b,a mod b)。其计算原理依赖于定理:两个整数的最大公约数等于其中较小的那个数的和两数相除余数的最大公约数,gcd(a,b)=gcd(b,a mod b)。定理证明前往百度百科。  示意图:


实现代码:

int gcd(int a,int b){
	if(b==0) return a;
	else return gcd(b,a%b);
}

扩展欧几里德算法

    是用来在已知 a , b 求解一组 x , y ,使它们满足贝祖等式:ax+by=gcd( a , b )  (解一定存在,根据数论中相关定理);常用在求解模线性方程及方程组中。

现在来看,知道了a和b的最大公约数gcd,一定有这样的x和y,使得 a*x+b*y=gcd,这是一个不定方程(其实是一种丢番图方程),有多解是一定的,但我们只要找到一组特殊解x0 和y0,那么可以用特解表示出整个的不定方程的通解:

定理1:设a,b是整数且d=gcd(a,b)。如果c不能被d整除那么方程ax+by=c没有整数解。如果c能被d整除那么存在无穷多个整数解,另外,如果x=x0,y=y0是方程的一个特解,那么所有的解可以表示为:(线性丢番图方程)

x=x0 + ( b / d )*t  ; 

y=y0 + ( a / d )*t ; 其中 t 为任意整数

那么如何求出特解x0和y0呢,就是在欧几里得算法稍稍改动。

欧几里德算法的停止状态为:a=gcd , b=0; 那么在这个状态可知 a的系数是1,b因为是0,系数无所谓多少,在这让b的系数也为0了,此时 a*1+b*0=gcd ; 当然此时也是最终状态,那么我们也就可以根据这个最终状态倒推回去,倒退到a=a的原值,b=b的原值,那么此时 a , b的系数 x 和y不就是我们要求的特解x0和y0 


代码实现:

//采用递归的形式 
int e_gcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int ans=e_gcd(b,a%b,x,y);
	int temp=x;
	x=y;
	y=temp-a/b*y;
	return ans;
}

乘法逆元

a*x=1( mod m) ,我们称 x 是 a 关于 m 的乘法逆元,等价于 a * x +m * y = 1; 当gcd( a , m ) != 1 时,无解。所以gcd( a , m ) = 1 是有解的充要条件,又扩展欧几里得算法,我们一般能找到无数解,题目一般会让输出最小的那组,我们可以得到一个特殊解x0(扩展欧几里德算法),x0 % m 就是最小解了。

因为:通解 x = x0 + m * t ; 也就是说 a 关于 m 的逆元是一个关于 m 同余的,那么一定存在一个最小正整数,它是 a 关于 m 的逆元,肯定在(0,m)之间,而且只有一个。

有时候由于问题的特殊性,我们得到的特解 x0 是一个负数(%与mod的不同),当 x0 为负数是,x0 mod m 结果仍为负(在计算机中用%代替mod的原因,注意%d,mod的区别),所以要对 x 稍加处理。

代码实现:要加上扩展欧几里德算法e_gcd(int a,int b,int &x,int &y)函数

int modReverse(int a,int m)
{
	int x,int y;
	int ans=e_gcd(a,m,x,y);
	if(ans==1)//有解的充要条件 
		return (x%m+m)%m;//最小逆元,+m是将负数变为正数 
	else
		return -1;//无逆元 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值