扩展欧几里得算法
来源:互联网 发布:linux suspend resume 编辑:程序博客网 时间:2024/06/18 16:28
扩展欧几里得
扩展欧几里得算法,是使用与如下问题的一种复杂度为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),就是原方程的一组可行解了。
- 欧几里得算法&&扩展欧几里得算法
- 欧几里得算法/扩展欧几里得算法
- 欧几里得算法&&扩展欧几里得算法
- 欧几里得、扩展的欧几里得算法
- 欧几里得及欧几里得扩展算法
- 欧几里得、扩展的欧几里得算法 .
- 欧几里得与扩展欧几里得算法
- 欧几里得和扩展欧几里得算法
- 欧几里得和扩展欧几里得算法
- 欧几里得算法及扩展欧几里得
- 欧几里得和扩展欧几里得算法
- 欧几里得, 扩展欧几里得算法模板
- 欧几里得算法及其扩展
- 扩展的欧几里得算法
- 扩展的欧几里得算法
- 欧几里得扩展算法
- 扩展欧几里得算法
- 扩展欧几里得算法
- 利用策略模式与装饰模式扩展JavaScript表单验证功能
- linux网络编程:使用进程池实现TCP多客户服务
- mongodb和oracle的区别
- hdoj2019
- 2017/2/15
- 扩展欧几里得算法
- UVA 2612 Find a way(BFS)
- img (内联元素) (inline元素) 标签上下左右间隙问题原因及解决方案: 垂直方向间隙和水平方向间隙原因及解决方案:
- hdoj2020
- jquery ajax 使用
- Eclipse导入GitHub项目
- CThread - a Worker Thread wrapper class
- 数组有没有length()方法?String类有没有?
- hdoj2035