欧几里得

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;
}

返回值就是逆元,d是gcd(a,b);

原文地址:https://www.cnblogs.com/wzl19981116/p/9358840.html