您的位置:首页 > 其它

扩展欧几里得+逆元

2016-10-05 17:06 363 查看
【传送门】参考了几位大神的资料,本蒟蒻表示不胜感激

http://chhaj5236.blog.163.com/blog/static/112881081200942542255916/(真心膜拜)

http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

http://blog.sina.com.cn/s/blog_7064e7850100yeu1.html

【扩欧的求法】经典的欧几里得算法早就烂熟于心,但是对于扩欧我原来一无所知。扩展欧几里德主要是用来与求解线性方程相关的问题。现在假设一个方程为a*x+b*y=m,如果这个线性方程有解,那么一定有gcd(a,b)
| m,即a,b的最大公约数能够整除m(m%gcd(a,b)==0)。

{证明}很简单,由于a%gcd(a,b)==b%gcd(a,b)==0,所以a*x+b*y肯定能够整除gcd(a,b)。

那么以下是关于此方程的解法:

令a1=a/gcd(a,b),b1=b/gcd(a,b),P=m/gcd(a,b)。如果我们能够首先求出满足a*x1+b*y1=gcd(a,b)(即原式两边除以P)这个方程的x1和y1,那么x=x1*P,y=y1*P就可以求出来了。由欧几里德算法gcd(a,b)=gcd(b,a%b),所以a*x1+b*y1=gcd(a,b)=gcd(b,a%b)=b*x2+(a%b)*y2,现在只要做一些变形就可以得到扩展欧几里德算法中的用到的式子了。令k=a/b(商),r=a%b(余数),那么a=k*b+r。所以r=a-k*b,带入上式,得到a*x1+b*y1=b*x2+(a-(a/b)*b)y2=a*y2+b*(x2-(a/b)*y2) => x1=y2,y1=x2-(a/b)*y2。有了这两个式子我们就知道了在用欧几里德求最大公约数的时候,相应的参数x,y的变化。现在再回过头来看一下扩展欧几里德算法的代码就很好理解了,实际上扩展欧几里德就是在求a和b的最大公约数的同时,也将满足方程a*x1+b*y1=gcd(a,b)的一组x1和y1的值求了出来。

【代码】

int exGcd(int a,int b,int &x,int &y)
{
if(b==0){x=1;y=0;return a;}
int g=exGcd(b,a%b,x,y);
int temp=x;x=y;
y=temp-(a/b)*y;
return g;
}

最后再乘上P,你懂的。这就是一组解。
【逆元】设我们要求a/b%p的值,我们可以转化为a*x%p。显然,(1/b)%p=x%p,x*b%p=1。

前提:gcd(x,b)=1.这样的话,x就存在。

如何求解a*x%n=1的方程呢?我们可以化成ax+ny=1,然后在上述gcd中带出。

【疑问】为什么网上的逆元模板都是有3个x和y的。= =

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: