欧几里得
1.欧几里得原理是辗转相除法,用来求最大公约数的;
int gcd(int x,int y)
{
return y==0?x:gcd(y,x%y);
}
2.拓展欧几里得原理,可以用来解二元一次方程:AX+BY=C;
模板 (返回值是gcd(a,b))
ll exgcd(ll a,ll b,ll &x,ll &y)//x,y在输入的时候不用定义
{
int d, t;
if(b==0)
{
x=1;
y=0;
return a;
}else
{
d = exgcd(b, a % b, x,y);
t = x - a / b * y;
x = y;
y = t;
return d;
}
}
因为用的是AX+BY=gcd(A,B),所以结果x,y要乘上 c/gcd(a,b)!!!!!
int ans=exgcd(int a,int b),如果C%ans!=0,方程无解,因为C=k1ansx+k2ansy=ans(k1x+k2*y) k1,k2,x,y都是整数,所以一定能整除,不然就无解
然后解的x1,y1是其中的一组解,x通解是x1+b*t/ans;t是次数,如果要求最小解,加上
while(x1>0) x1-=b/ans;
x1+=b/ans;
或者
x=(c/ans*x%(b/ans)+b/ans)%(b/ans);
3.求逆元
因为逆元是ax=1(mod m),x为a的逆元,而欧几里得是求ax+by=c,修改一下,ax+b*m=1,解出x则可求出逆元
首先如果gcd(a,m)!=1,则无解,这也是 ax + by = c 有解的充要条件: c % gcd(a , b) == 0
最后带入模板,然后调整x的值使其在0~m-1之间就好了
ll gcd(ll a,ll b,ll &d,ll& x,ll& y){
if(!b){
d=a;
x=1;
y=0;
return x;
}
else{
gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
while(x<0) x+=b;
return x;
}