浅谈中国剩余定理

数论基础篇吧,与Exgcd有脱不开的关系。

这个算法,就是要让我们求n个线性同余方程的共同解的最小值,即最小整数解。

我们可以设:M为所有模数之积,Mi=M/b[i],ti为Mi*ti在模ai(模数)意义下同余1的方程的一组解,且模数均互质。

我们则有:方程组的特解为M1*t1*b1+...+Mn*tn*bn.

证明:因为Mi是除了ai之外所有模数的倍数,所以对于任意k≠i,都有bi*Mi*ti≡0(mod ak

又因为bi*Mi*ti≡bi(mod ai),所以x=∑bi*Mi*ti带入原方程组成立。

对于T我们直接用Exgcd求解即可。其通解可以表示为x+kM,我们求最小非负整数解时,将x对M取模,并让它落在0~M-1的区间中即可。

代码实现:

inline void Exgcd(LL a,LL b,LL &d,LL &x,LL &y){
    if(!b){d=a;x=1;y=0;}
    else{
        Exgcd(b,a%b,d,x,y);
        LL t=x;x=y;y=t-(a/b)*y;
    }
}
inline LL IntChina(){
    LL Ans=0,Mi,x,y,d;
    for(LL i=1;i<=n;++i){
        Mi=M/a[i];
        Exgcd(Mi,a[i],d,x,y);
        Ans=((Ans+Mi*x*b[i])%M+M)%M;
    }return (Ans+M)%M;
}

例题:曹冲养猪

中国剩余定理模板题,用上面代码足以AC,代码不在给出。

例题:猜数字

这题也算是中国剩余定理的模板题目了,我们列出方程后,只需要进行一下移项,转移成我们熟悉的样子,套用中国剩余定理求解即可。

注意两点:注意将负数转成非负数。

注意要用龟速乘。这里大概讲一下龟速乘:

二进制算法,我们将因数b每次除以2,a每次乘以2,判断b的当前一位是不是1(二进制下),如果是,则说明对最终结果有贡献,便让ans+=a,ans%=mod.注意每次取余。

这里给出龟速乘的代码,本题代码不再给出。(毕竟笔者这个蒟蒻都自己水了90pts,没用龟速乘。)

代码:

#define ll long long
ll Ksc(ll a,ll b,ll mod){
    ll ans=0;
    for(;b;b>>=1,a=(a+a)%M)if(b&1)ans=(ans+a)%mod;
    return ans;
} 

 

posted @ 2019-07-21 20:06  Refined_heart  阅读(217)  评论(0编辑  收藏  举报