【知识点】中国剩余定理(CRT)

【用途】解决一元线性同余方程组

 

 

【板子(m之间互素)】

/*
中国剩余定理板子(基础)
设余数为c[i],模数为m[i],令M为m[i]之和
那么最终答案就是c[i](M/m[i]) inv((M/m[i]),m[i])之和modM
解是唯一的,而且由于每个mod都m个不同的情况,所以恰好可以涵盖所有情况。
*/
ll c[maxn],m[maxn],M;//i从1开始
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
ll getInv(ll a,ll mod)
{
    ll x,y,d;
    d=exgcd(a,mod,x,y);
    return d==1?(x%mod+mod)%mod:-1;
}
ll CRT(int n)
{
    M=1;
    for(int i=1;i<=n;i++)M*=m[i];
    ll ret=0;
    for(int i=1;i<=n;i++)
        ret=(ret+c[i] * (M/m[i]) %M * getInv(M/m[i],m[i]) )%M;
    return ret;
}

 

 

【板子(扩展)】

/*
中国剩余定理板子(扩展)
在mo数不两两互素之时
*/
ll m[maxn],c[maxn];//从1开始
ll gcd(ll a,ll b)
{
    return !b?a:gcd(b,a%b);
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
ll getInv(ll a,ll mod)
{
    ll x,y;
    ll d=exgcd(a,mod,x,y);
    return d==1?(x+mod)%mod:-1;
}
ll exCRT(int n)
{
    ll m1,m2,c1,c2,d;
    for(int i=2;i<=n;i++)
    {
        m1=m[i-1],m2=m[i],c1=c[i-1],c2=c[i];
        d=gcd(m1,m2);
        if((c2-c1)%d)return -1;//此时无法合并
        m[i] = m[i-1] * m[i] / d;
        c[i] = (c2-c1)/d * getInv(m1/d,m2/d) % ( m2 / d ) * m1 + c1;
        c[i] = ( c[i] % m[i] + m[i] ) % m[i];
    }
    return c[n];
}

 

 

【证明】

我还没学啦,详细看链接

https://www.cnblogs.com/MashiroSky/p/5918158.html

 

【习题】

hdu 1573

 

 

【参考链接】

https://blog.csdn.net/xiaoming_p/article/details/79672049

posted @ 2020-01-12 14:17  carrotmvp  阅读(306)  评论(0编辑  收藏  举报