[学习笔记]合并线性同余方程

合并线性同余方程

一.问题引入

再做题过程中,我们可能会遇到这样的情况:
\[ \begin{align} x\equiv r_1(mod\;m_1)\\ x\equiv r_2(mod\;m_2)\\ x\equiv r_3(mod\;m_3)\\ .... \end{align} \]
要对这些线性同余方程求解,而我们可以通过合并方程解决这种问题。

二.解决方法

先来看看对于单独的两个同余方程。
\[ x\equiv r_1(mod\;m_1)\\ x\equiv r_2(mod\;m_2)\\ \]
很显然的,它们可以变为如下两个不定方程。
\[ x=k_1*m_1+r_1\\ x=k_2*m_2+r_2\\ \]
联立可得
\[ k_1*m_1+r_1=k_2*m_2+r_2\\ k_1*m_1+k_2*m_2=r_2-r_1 \]
所以我们可以用扩展欧几里得算出有关于\(x\)的一个特解\(x_0\),并且我们知道这么几个式子
\[ \begin{align} &x_0=k_1*m_1+r_1\\ &x=k_i*m_1+r_1\\ &k_i=u*\frac{m_2}{gcd(m_1,m_2)}+k_1(u\in Z)\\ &x=u*\frac{m_1m_2}{gcd(m_1,m_2)}+k_1*m_1+r_1\\ &x=u*lcm(m_1,m_2)+x_0 \end{align} \]
于是我们呢可以变形得到关于x的一个式子
\[ x\equiv x_0(mod\;lcm(m1,m2)) \]
于是我们便将两个同余方程合并成了一个

三.代码

#define ll long long
ll Exgcd(ll a,ll b,ll &x,&y){
    if(b==0){
        x=1,y=0;return a;
    }
    ll d=Exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
ll n,right[1000],mod[1000];
ll solve(){
    for(int i=1;i<n;++i){
        ll a=mod[i],b=mod[i+1],c=right[i+1]-right[i],x,y,zy,zx;
        ll d=Exgcd(a,b,x,y);
        if(c%d)return -1;
        a/=d,b/=d,c/=d;
        x=((x*c)%b+b)%b;
        mod[i+1]=mod[i]/Exgcd(mod[i],mod[i+1],zx,zy)*mod[i+1];
        right[i+1]=((x*mod[i]%mod[i]+right[i])%mod[i+1]+mod[i+1])%mod[i+1];
    }
    return right[n];
}

猜你喜欢

转载自www.cnblogs.com/clockwhite/p/12182528.html