扩展欧几里得是干什么的?给定两个数a,b,设Gcd(a,b)=d(d是a,b的最大公约数),则存在整数x,y,使得x*a+y*b=d。
扩展欧几里得可以求出x,y。怎么求呢?我们知道,Gcd(a,b)=Gcd(b,a%b),而我们也就是运用这个东西来求a和b的最大公约数的。
因此,设bx+(a%b)y=d,即bx+(a-a/b*b)y=d,所以:ay+b*(x-a/b*y)=d。因此我们可用下面的代码解决:
int64 exGcd(int64 a,int64 b,int64 &x,int64 &y)
{
int64 r,t;
if(b==0)
{
x=1;
y=0;
return a;
}
r=exGcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return r;
}
这个程序返回值为Gcd(a,b),ax+by=Gcd(a,b),其中x,y分别存在x,y中。
当然,如果给出的是求ax+by=c,这时当且仅当Gcd(a,b)可以整除c时x,y有整数解。这个很好证明,设Gcd(a,b)=d,那么a=d*k1,b=d*k2,所以ax+by=d*(k1*x+k2*y),即ax+by必为d的倍数,所以c必为d的倍数,即d必能整除c。这样的话,先求ax+by=d的一组解x0,y0,设k=c/d,则k*x0,k*y0就是一组解。
另外,扩展欧几里得可以求乘法逆元。乘法逆元的意思就是对于a,p,若存在b使得ab%p=1,则称b为a对p的乘法逆元。那么这个b有什么意思呢?对于一个数x,x/a%p=x*b%p(a可以整除x)。这样的话,就可以将除法变为乘法,那么为什么上式成立呢?设x=k*a,则x/a%p=k%p=(k%p)*(ab%p)=(k*a*b)%p=x*b%p。那么怎么求b呢?ab%p=1,我们可得ab=kp+1(k为某个整数),即ab-kp=1,令x=b,y=-k,则我们求出ax+py=1的一组解x,y即可。这个式子有解的充要条件是Gcd(a,p)=1.
证明如下:
(1)若Gcd(a,p)=1,有欧拉定理,设Ψ(x)表示x的欧拉函数(Ψ(x)是一个数,是[1,x-1]中与x互质的数的个数),(a^Ψ(x))%p=1,所以b=a^(Ψ(x)-1)就是一个答案;
(2)若ab%p=1,则ab=kp+1,ab-kp=1,设Gcd(a,p)=d,则d必能整除1,所以d只能是1。
这样的话就能用上面的代码求了。。。