数论学习之扩展欧几里得
数论之扩欧
QB_UDG 2016年11月8日11:34:40
- 1. 扩展欧几里德算法
用途:在已知整数a,b的情况下求不定方程ax+by=gcd(a,b)的一组整数解x,y;
原理:
设 a*x1+b*y1=gcd(a,
b);
设
b*x2+(a%b)*y2=gcd(b, a%b);
由欧几里德定理知: gcd(a, b)==gcd(b, a%b)
所以==>a*x1+b*y1=b*x2+(a%b)*y2
也就是==>a*x1+b*y1=b*x2+(a-(a/b)*b)*y2
展开得到==>a*x1+b*y1=b*x2+a*y2-b*(a/b)*y2
转换得到==>a*(x1)+b*(y1)=a*(y2)+b*(x2-(a/b)*y2)
观察上式可知,对于(a,b)的不定方程可以转换为(b,a%b)的不定方程
x1=y2,
y1=x2-a/b*y2
从这里可以看出,x1,y1可以由下一步的x2,y2推出来,所以最初解可以在递归回溯的时候求解。
那什么时候是终止呢?也就是递归gcd(a, b)中b=0时
即gcd(a, 0)此时 a*x+b*y==gcd(a, b)知 a*x+b*y=a
解出x=1, y=0; 此时就是递归终止的地方。
代码实现:
int extended_ (int a, int b, int &x, int &y)
{
int r, tmp;
if (b==0) { x = 1; y = 0; return a; }
r = extended_gcd(b, a % b, x, y);
tmp = x; x = y; y = tmp - a / b * y;
return r;
}
应用:
1.求ax+by=c的通解。
如果c%gcd(a,b)!=0) 则无解。
若有解:
先求出ax’+by’=gcd(a,b) 的一组解x’,y’;
则原方程的一组解为x=x’*c/gcd(a,b),y=y’*c/gcd(a,b);
若要求通解:
因为ax+by=a(x+kb)+b(y-ka)=c; k是整数;
所以原方程的通解为x=x+k*b,y=y-k*a;
2.解模线性方程 => ax ≡ b (mod n)
即ax%n=b%n
转换为(ax-b)%n=0 也就是ax-b=ny
所以也就转换为了求ax-ny=b的解;
3.乘法逆元
在同于方程的意义下,a的逆元常记为a-1,不是传统的指数概念,
只是表示:a*a-1≡1(mod n)
由前面的讨论可知:不定方程ax-ny=1要有解。
这样1必须是gcd(a,n)的倍数,因此a和n必须互质,且ax≡1(mod n)只有唯一解,此解即为a在模n下的乘法逆元a-1
注意:通过扩欧算出的不定方程有很多解,最终的逆元应该是x%n,也就是逆元的范围是[0,n-1]
求ax≡1(mod n)的乘法逆元,若不存在,返回-1
long long Inverse(long long a,long long
n)
{
long long x,y;
if(extended_gcd(a,n,x,y)==1)return (x+n)%n; else return -1;
}
在执行完extended_gcd()后,x可能为负数,加上n后将其变为整数。取
模运算对于加、减、乘有分配率,但对除没有。
乘法逆元可在同余式中把除法改为乘法。
(a*b) mod p==((a mod p)*(b mod p)) mod p
(a/b) mod p != ((a mod p)/(b mod p)) mod p
但是我们可以把(a/b) mod p 改写成 (a*b-1) mod p
((a/b)mod p==(a*b-1)mod p==((a mod p)*(b-1 mod
p)) mod p