数论之扩展欧几里德相关模板

拓展欧几里得公式:

typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y){
     if(a==0&&b==0) return -1;
     if(b==0) { x=1;y=0; return a;  }
     LL d=exgcd(b,a%b,y,x);
     y-=a/b*x;
     return d;
}

解ax+by=c的解集:

typedef long long LL;
LL x0,y0,kx,ky;
bool LE(LL a,LL b,LL c){   //解线性方程ax+by=c
    LL x1,y1;
    LL gcd=exgcd(a,b,x1,y1);
    if(c%gcd)
        return false;  //无整数解
    x0=x1*c/gcd;  //一组解
    y0=y1*c/gcd;  //一组解
    kx=b/gcd;
    ky=-a/gcd;
    return true;   //有解,解集为:(x0+kx*t,y0+ky*t) t为整数
}

求解x的最小正整数解:

/* 求解出x的最小正整数解*/
typedef long long ll;
void minxx(int a, int b, int c, int x, int y)
{
    int gcd = exgcd(a, b, x, y);
    ll x1, y1, t;
    t = b / gcd;
    if( t<0 )
    {
        t = -t;
    }
    x1 = (x+t)*(c/gcd);
    x1 = (x1%t+t)%t;
    y1 = (c-a*x1)/b;
    printf("x==%lld, y=%lld\n", x1, y1);
    return ;
}
void minxx(ll a, ll b, ll c, ll x, ll y)
{
    int gcd = exgcd(a, b, x, y);
    ll x1, y1, t;
    t = b / gcd;
    if( t<0 )
    {
        t = -t;
    }
    x1 = x;
    x1 = (c/gcd*x1%t+t)%t;
    y1 = (c-a*x1)/b;
    printf("%lld %lld\n", x1, y1);
    return ;
}

同余方程 ax≡b (mod n)对于未知数 x 有解,当且仅当 gcd(a,n) | b(即b%gcd(a, b)==0 ),且方程有解时,方程有 gcd(a,n) 个解。

求解方程 ax≡b (mod n) 相当于求解方程 ax+ ny= b, (x, y为整数)

求解线性同余方程:

bool modular_linear_equation(int a,int b,int n)
{
    int x,y,x0,i;
    int d=exgcd(a,n,x,y);
    if(b%d)
        return false;
    x0=x*(b/d)%n;   //特解
    for(i=1;i<d;i++)
        printf("%d\n",(x0+i*(n/d))%n);
    return true;
}

同余方程ax≡b (mod n),如果gcd(a, n)==1, 则方程只有唯一解。

这种情况下,如果b==1,同余方程就是ax=1(mod n), gcd(a, n)=1.

这时称求出的x为a的对模n乘法的逆元。

对于同余方程ax=1(mod n), gcd(a, n)=1 的求解就是求解方程ax+ny=1, x, y 为整数。

ll inv(ll a, ll n)
{
    ll d, x, y;
    d = exgcd(a, n, x, y);
    return (d==1)?(x%n+n)%n:-1;
}

猜你喜欢

转载自www.cnblogs.com/wsy107316/p/11354809.html