乘法逆元
给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的。
一扩展欧几里得可以求最大公约数。
二求ax+by=gcd(a,b)的解x,y。逆元就包括其中。
x是a的模b乘法逆元,y是b的模a乘法逆元(即gcd()=1时的x/y)
现在来讲一下扩展欧几里得到底怎么来的:
其实我觉得大家只要搞懂后面递归的x,y怎么求就几乎没问题的了。
原式:ax+by=gcd(a,b)
递归:bx+(a%b)y^=gcd(a,b) 【x^和 y^就是上一步的x,y】
其中:a%b=a-(a/b)b
带入后:ay^+b ( x ^ - ( a/b ) y ^ )=gcd(a,b);
再与原式对比:ax+by=gcd(a,b)
得出:{
x=y^;
x^-(a/b ) y ^=y;
}
这就是递归过程中,x和y的由来
而当b=0时,有:(递归结束时){a=gcd(a,b),x=1,y=0}
a1+b0=a=gcd(a,b)
可得出一个特解a(最大公约数)
这样就可以得到每两个相邻状态的x和y的转化了,就可以在求gcd(a,b)的同时求对x,y求解
相信对于扩展欧几里得算法,大家会有疑问为什么b=0时x=1;y=0?
其实当达到递归基时,此时的a就是gcd(最大公约数),b=0,那么有ax+by=a。
故x必须等于1,y可以取任何正整数。
我还是有疑问上面说了“x是a的模b乘法逆元,y是b的模a乘法逆元”
大家都统一b=0时x=1;y=0;。既然y可以取任何正整数那么我就要换一个当b=0时:x=1;y=1;这个“x是a的模b乘法逆元,y是b的模a乘法逆元”结论还是成立的。
还有一点就是建议y取0,如果取其他数组,由于y增长较快,可能会有越界的问题。
int exGcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int gcd=exGcd(b,a%b,x,y);
int t=x;
x=y;
y=t-(a/b)*y;
return gcd;
}
signed main()
{
int n,m;
int x,y;
cin>>m>>n;
if(exGcd(n,m,x,y)==1)
{
cout<<(y%n+n)%n<<endl;
}
else
{
cout<<-1<<endl;
}
return 0;
}