5.扩展欧几里得&&中国剩余定理

1. 求解不定方程
ax+by=gcd(a,b)
求|x|+|y|最小值
void Ex_gcd(LL a,LL b,LL& d,LL& x,LL& y)
{
    if(!b)
        {d=a;x=1;y=0;}
    else
    {
        Ex_gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
(x,y)的所有解:
g=c/d;a=a/d;b=b/d;
x=g*x0+b*t;
y=g*y0-a*t;


2. 求解模的逆元
ax=1(mod n);
存在条件:gcd(a,n)=1;
LL inv(LL a,LL n)
{
    LL d,x,y;
    Ex_gcd(a,n,d,x,y);
    return d==1?(x+n)%n:-1;
}

3. 求解同余方程
(1) 求解一次同余方程:ax=b(mod m) 即:ax+my=b所有解:
LL f(LL a,LL b,LL m)
{
    Ex_gcd(a,m,d,x,y);
    if(b%d) return -1;
    x=x*(b/d)%m;
    for(i=1;i<=d;i++)
        ans[i]=(x+(i-1)*m/d)%m;
}       ///如果ans[i]为负数,则可以加上m


(2)求解一元线性同余方程组(中国剩余定理)
x=r1(mod a1)
x=r2(mod a2)
...
x=rn(mod an)
求解x的最小值:
LL solve()
{
    scanf("%lld%lld",&a1,&r1);
    for(i=1;i<n;i++)
    {
        scanf("%lld%lld",&a2,&r2);
        a=a1;b=a2;c=r2-r1;
        Ex_gcd(a,b,d,x0,y0);
        if(c%d!=0) ifhave=0;
        LL t=b/d;
        x0=(x0*(c/d)%t+t)%t;
        r1=a1*x0+r1;
        a1=a1*(a2/d);
    }
    if(!ifhave) r1=-1;
    return r1;


如果ai两两互素:
x=a1(mod m1)
x=a2(mod m2)
...
x=an(mod mn)
LL China()
{
    M=1;
    LL i,Mi,x0,y0,d,ans=0;
    for(i=1; i<=n; i++)
        M*=m[i];
    for(i=1; i<=n; i++)
    {
        Mi=M/m[i];
        Ex_gcd(Mi,m[i],d,x0,y0);
        ans=(ans+Mi*x0*a[i])%M;
    }
    if(ans<0) ans+=M;
    return ans;
}

你可能感兴趣的:(数论)