中国剩余定理CRT

在中国带孩子是一件非常痛苦的事(当然不包括可爱的妹子们呢)QAQ

然鹅,我们现在拥有一堆 孩子 方程

  • \(x\equiv a_1mod(p_1)\)
    \(x\equiv a_2mod(p_2)\)
    \(…\)
    \(x\equiv a_nmod(p_n)\)
    \(p_1,p_2…p_n 两两互质\),求最小的正整数x
  • 设M为\(p_1,p_2…p_n\)的积
    设Mi为M/\(p_i=>M_i与p_i互质\)
    \(x_i\equiv1(modp_i),且x_i\equiv0(modM_i)=>x_i \equiv0 mod(p_{abcdefghj…}就是不等于i)\)
    ****也就是说\(x_i=k_iM_i\equiv1(mod)p_i\)然后我们可以通过求\(M_i\)的逆元\(k_i\)求得\(x_i\)****
  • 根据同余定理
    \(a_ix_i\equiv a_imod(p_i)\)
    再根据同余定理
    ****则通解x为 \(\sum(a_ix_i)modM\)****

综****上****所诉x=((\(\sum(a_ik_iM_i)modM+M)mod M)\)


扩展
EXCRT

  • \(x\equiv a_1mod(p_1)\)
    \(x\equiv a_2mod(p_2)\)
    \(…\)
    \(x\equiv a_nmod(p_n)\)
    \(p_1,p_2…p_n 不一定互质\),求最小的正整数x
    现在假设我们已知 \(x\equiv a_1mod(p_1),x\equiv a_2mod(p_2)\)
    \(也就是说x=a_1+k_1p_1=a_2+k_2p_2\)
    \(k_1p_1-k_2p_2=a_2-a_1\)用exgcd解出一组通解
    因为x min 所以\(x_1\) min;
    通过\(也就是说x=a_1+k_1p_1\)求出最小通解x'
    合并成一个新的方程\(x≡x' \pmod {lcm(m1,m2))}\)

    算法
    考虑合并(发现的一个有意思的证明)

\(\left\{\begin{aligned}x\equiv B \pmod A\\x\equiv b_i\pmod {a_i}\\\end{aligned}\right.\)i

\(x=Am_1+B=a_im_2+b_ix=Am\therefore Am_1-a_im_2=b_i-B\)

由于bezoutbezout定理,
\(gcd(A,a_i)|(b-B)\)
否则无解。

\(设G=gcd(A,a_i)G=gcd(A,ai)\therefore A\frac {m_1G}{b_i-B}+a_i\frac {m_2G}{b_i-B}=G\)

\(t_1=\frac {m_1G}{b_i-B},t_2=\frac {m_2G}{b_i-B} \therefore At_1+a_it_2=G\)

\(用exgcd解出一组特解t_x,t_y\)
根据不定方程特解公式:

\(t_1=t_x+d\frac {a_i}{G}\)

\(m_1=(t_x+d\frac {a_i}{G})\frac {b_i-B}{G}\)
\(x=A(t_x+d\frac {a_i}{G})\frac {b_i-B}{G}+B\)
\(x=At_x\frac {b_i-B}{G}+d\cdot A\frac {a_i}{gcd(a_i,A)}\frac {b_i-B}{G}+B\)
\(x=At_x\frac {b_i-B}{G}+d\cdot lcm(A,a_i)\frac {b_i-B}{G}+B\)

显然d=0解最小,所以原方程最小解

\(x=At_x\frac {b_i-B}{G}+B\)
合并之后的通解就是

\(x\equiv At_x\frac {b_i-B}{G}+B \pmod {lcm(A,a_i)}\)

#include<bits/stdc++.h>
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=1e5+5;
typedef long long ll;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}
using namespace std;
int n;
ll ans,LCM,x,y,a[maxn],b[maxn];

ll EXGCD(ll a,ll b,ll &x,ll&y)
{
    if(!b){x=1;y=0;re a;}
    ll d=EXGCD(b,a%b,x,y);
    ll z=x;
       x=y;
    y=z-(a/b)*y;
    re d;
}

ll vivi(ll k,ll n,ll mod)
{
    ll ans=0;
    while(n)
    {
        if(n&1)ans=(ans+k)%mod;
        n>>=1;
        k=(k+k)%mod;
    }
    re ans;
}

int main()
{
//  freopen("vv.txt","r",stdin); 
    rd(n);
    inc(i,1,n)
    rd(b[i]),rd(a[i]);
    ans=a[1];
    LCM=b[1];
    inc(i,2,n)
    {
        ll B=((a[i]-ans)%b[i]+b[i])%b[i];
        //k1*p1-k2*p2=a2-a1=d
        ll gcd=EXGCD(LCM,b[i],x,y);
        x=vivi(x,B/gcd,b[i]);
        //x1=k1*(d/g)
        ans+=LCM*x;
        //x=a1+k1*p1
        LCM*=b[i]/gcd;
        ans=(ans+LCM)%LCM;
        
    }
    printf("%lld\n",ans);
    re 0;
}

猜你喜欢

转载自www.cnblogs.com/lsyyy/p/11252518.html