Crt and ExCrt

### $Crt$

求解不定方程组

img

\(M=\prod\limits_i^nm_i\)

\(M_i=\frac{M}{m_i}=\prod\limits_{k,k\neq i}^nm_k\)

\(t_i\)\(M_i\)在模\(m_i\)时的逆元

先上结论 通解为\(\sum\limits_i^na_iM_it_i mod LCM(m_i)\)

证明:

对于方程组中第\(i\)个方程考虑

\(\because M_k(k\neq i) mod  m_i=0\)

\(\therefore \sum\limits_{k,k\neq i}^na_kM_kt_k\equiv0 (mod m_i)\)

\(\because t_iM_i\equiv1 (mod m_i)\)

\(\therefore a_iM_it_i\equiv a_i (mod m_i)\)

$\therefore \sum\limits_i^na_iM_it_i\equiv a_i (mod m_i) $

解合法

得证,通解为\(\sum\limits_i^na_iM_it_i mod LCM(m_i)\)


void exgcd(int a,int b,int &x,int &y)
{
    if(b==0){ x=1; y=0; return;}
    exgcd(b,a%b,x,y);
    int tp=x;
    x=y; y=tp-a/b*y;
}

int china()
{
    int ans=0,lcm=1,x,y;
    for(int i=1;i<=k;++i) lcm*=b[i];
    for(int i=1;i<=k;++i)
    {
        int tp=lcm/b[i];
        exgcd(tp,b[i],x,y);//求逆元
        x=(x%b[i]+b[i])%b[i];//x要为最小非负整数解
        ans=(ans+tp*x*a[i])%lcm;
    }
    return (ans+lcm)%lcm;
}

ExCrt

扩展中国剩余定理解决的是\(m_i\)不互质的问题

不再是宏观上直接构造一个通解,因为它的通解无法直接用公式表示

用归纳法,考虑前\(k-1\)个方程的通解为\(x(mod M), M=LCM(m_1到m_{k-1})\)

我们为了符合第\(k\)个方程,需要加一些数,但为了保证前\(k-1\)个方程仍然成立,所以只能加若干倍的\(M\),也就是说找到\(x+t*M\equiv a_k(mod m_k)\)

上式整理得\(t*M\equiv a_k-x(mod m_k)\)

可以用扩展欧几里得求解,若同余方程无解则整个方程组无解

否则新的解为\(x+t*M(mod LCM(M,m_k))\)

有一些细节对代码解释

lt exgcd(lt a,lt b,lt &x,lt &y)
{
    if(b==0){x=1;y=0;return a;}
    lt gcd=exgcd(b,a%b,x,y);
    lt tp=x;
    x=y; y=tp-a/b*y;
    return gcd;
}

lt excrt()
{
    lt x,y,k;
    lt M=bi[1],ans=ai[1];//一开始赋为初始值
    for(int i=2;i<=n;i++)
    {
        lt a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;//注意取模保证是正数
        lt gcd=exgcd(a,b,x,y),bg=b/gcd;//t*M-y*mk=gcd,gcd为M和mk的gcd
        if(c%gcd!=0) return -1; //因为求解是根据gcd而不是c,所以还要乘倍数,如果不是倍数证明无解
        
        x=mul(x,c/gcd,bg);//将x乘倍数,这里取模mk/gcd的原因是x(也就是t)还要乘M,乘M之后不能超过LCM(M,mk),也就是不能超过M*m/gcd,所以这里直接对m/gcd取模即可
        ans+=x*M;//答案更新
        M*=bg;//模数更新
        ans=(ans%M+M)%M;//处处取模小心负数
    }
    return (ans%M+M)%M;
}

posted @ 2019-08-18 18:34  __Liuz  阅读(97)  评论(0编辑  收藏  举报