扩展欧几里得算法

扩展欧几里得

扩展欧几里得算法,是使用与如下问题的一种复杂度为log(n)级别的算法:
求ax+by=gcd(a,b)的整数解。
首先,求解这个方程,其实只需要求出一组可行解,其他的解都是可以用这一组可行解推出来的,假设我们已经求得一组可行解x0,y0,那么对于任意的整数k, x0+k*b/(a,b),y0+k*a/(a,b)都是这个方程的一组解。
我们知道,gcd(x,y)=gcd(y,x mod y)(欧几里得算法),
这样,我们可以将问题转化为求方程bX+(a mod b)Y=gcd(a,b)的整数解,先来考虑边界,显然,当b=0时,x=1,y=0就是一组可行解,接下来就需要找出转化后的方程的解X,Y与原方程的解x,y的关系,联立方程:
**ax+by=bX+(a mod b)Y
因为a mod b=a-(a/b)*b,”/”为整除,所以,
ax+by=bX+aY-(a/b)*bY;移项,
a(x-Y)=b(X-(a/b)*Y-y);
所以,x=Y,y=X-(a/b)Y 是原方程的一组解。
代码如下:

void exgcd(int a,int b,int &x,int &y){
    if(!b){
        x=1;y=0;return;
    }
    int X,Y;
    exgcd(b,a%b,X,Y);
    x=Y;y=X-(a/b)*Y;
}

这个算法的时间复杂度如何估算呢,和欧几里得算法一样,每次mod最坏可以看成是/2,所以复杂度就是O(logn)的。

有时,扩欧会用来求解逆元:
什么是逆元?
逆元在求形如(a/b)mod m的时候非常有用,由于a/b可能是一个很大的数,直接求出来再mod显然不可行,写高精度有没有必要或是复杂度承受不了,就可以利用逆元把除法转化成乘法。我们定义b在模m的逆元为使bc mod m=1的最小正整数,这样的数有什么用呢?
(a/b)mod m*bc=(a/b*b*c)mod m=(a*c)mod m,由于bc mod m=1,所以这样的乘法并不会改变答案,而乘法的mod运算时满足分布mod的,这样就没有必要去写高精度了。下面我们来看如何求逆元:
得bc mod m=1,所以bc+my=1;
显然,只有当bm互质时,这个方程才有解,也就是说,逆元是有条件的,即bm需要互质,接下来,由于bm互质,那么gcd(b,m)就等于1,就可以用扩欧来求解这个问题了。

扩欧还可以用来求解如下方程:
ax+by=m,
显然,对于这样的方程,只有当gcd(a,b)是m的因子时,方程才有解,因为如果gcd(a,b)不是m的因子,那么等号的左边一定是gcd(a,b)的倍数,而右边又不是,所以方程一定无解,这样,我们可以将问题归化为求方程a/(a,b)*x+b/(a,b)*y=m/(a,b)的解,这样,设p=a/(a,b),q=b/(a,b),那么p与q互质,所以,就可以先求出方程px+qy=1的解,再将x和y分别乘m/(a,b),就是原方程的一组可行解了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值