中国剩余定理与线性同余方程组求解

中国剩余定理与线性同余方程组求解

线性同余方程组的形式

实际上一元一次线性同余方程组,形式如下:
{ x ≡ r 0 ( m o d   m 0 ) x ≡ r 1 ( m o d   m 1 ) ⋯ \begin{cases} x\equiv{r_0}({\rm{mod}}\,m_0) \\ x\equiv{r_1}({\rm{mod}}\,m_1) \\ \cdots \end{cases} xr0(modm0)xr1(modm1)
包含有具体数字的线性同余方程组问题最早见于《孙子算经》(成书于约南北朝时期,因此与《孙子兵法》的孙子应该不是同一个孙子),该书也给出了该具体问题的解法。因此求解线性同余方程组有关的定理又称作孙子定理。但实际上《孙子算经》并未给出证明及一般性解法。最早的系统性论述应该是南宋时期秦九韶在《算术九章》中提出的“大衍求一术”。因此最后有关该问题的理论被称作中国剩余定理。

中国剩余定理

如果 m 0 , m 1 , ⋯ m_0,m_1,\cdots m0,m1,两两互质,则方程有唯一解,在模 ∏ i m i \prod_{i}{m_i} imi的意义下。解法如下:
M = ∏ i m i M=\prod_{i}{m_i} M=imi,且 M i = M / m i M_i=M/m_i Mi=M/mi
对每一个 M i M_i Mi求出在模 m i m_i mi意义下的逆元,记作 x i x_i xi
即满足 M i ⋅ x i ≡ 1 ( m o d   m i ) M_i\cdot{x_i}\equiv1({\rm{mod}}\,m_i) Mixi1(modmi)
则原方程组的解为 x = ∏ i r i ⋅ x i ⋅ M i   m o d   M x=\prod_{i}{r_i\cdot{x_i}\cdot{M_i}}\,\rm{mod}\,M x=irixiMimodM

#线性同余方程组的一般解法
使用中国剩余定理理论上可以很方便的解出模数两两互质的方程组。对于不互质的情况可以使用下面的一般解法。
##单独的线性同余方程求解
考虑单独的一个线性同余方程,已知 a , b , m a,b,m a,b,m,求 x x x满足如下方程:
a x ≡ b ( m o d   m ) ax\equiv{b}({\rm{mod}}\,m) axb(modm)
原方程等价于:
a x + m y = b ax+my=b ax+my=b
根据裴蜀定理,上述方程有解的充要条件是 b b b g c d ( a , m ) gcd(a,m) gcd(a,m)的整数倍。利用扩展的扩展的欧几里德算法可以很容易求得 x 0 x_0 x0使得:
a x 0 + m y 0 = g c d ( a , m ) ax_0+my_0=gcd(a,m) ax0+my0=gcd(a,m)
于是很容易得到 x x x的一个特解为:
x = x 0 ⋅ b g c d x=x_0\cdot\frac{b}{gcd} x=x0gcdb
显然 x x x有无穷多解,如果考虑在模 m m m的意义下, x x x也有 g c d gcd gcd个不同的解,且成等差数列,公差为 m / g c d m/gcd m/gcd。因此很容易求得最小正整数解为:
x = x 0 ⋅ b g c d   m o d   m g c d x=x_0\cdot\frac{b}{gcd}\,\rm{mod}\,\frac{m}{gcd} x=x0gcdbmodgcdm
考虑方程
9 x ≡ 6 ( m o d   12 ) 9x\equiv6({\rm{mod}}\,12) 9x6(mod12)
根据扩展的欧几里德算法有:
9 x 0 + 12 y 0 = 3 9x_0+12y_0=3 9x0+12y0=3
得到 x 0 x_0 x0的一个解为11,所以 x x x的一个解为22,对4取模即可得到最小正整数解2,且在模12的意义下有3个解,分别是2、6、10。
##两个线性同余方程合并
考虑2个线性同余方程构成的方程组:
{ x ≡ r 0 ( m o d   m 0 ) x ≡ r 1 ( m o d   m 1 ) \begin{cases} x\equiv{r_0}({\rm{mod}}\,m_0) \\ x\equiv{r_1}({\rm{mod}}\,m_1) \end{cases} {xr0(modm0)xr1(modm1)
分别等价于
{ x = r 0 + m 0 z 0 x = r 1 + m 1 z 1 \begin{cases} x=r_0+m_0z_0\\ x=r_1+m_1z_1 \end{cases} {x=r0+m0z0x=r1+m1z1
因此有
m 0 z 0 = m 1 z 1 + r 1 − r 0 m_0z_0=m_1z_1+r_1-r_0 m0z0=m1z1+r1r0
两边对 m 2 m_2 m2取余数即可得到一个单独的关于 z 0 z_0 z0线性同余方程
m 0 z 0 ≡ r 1 − r 0 ( m o d   m 1 ) m_0z_0\equiv{r_1-r_0({\rm{mod}}\,m_1)} m0z0r1r0(modm1)
根据之前的结论,很容易判断是否有解并可以解出 z 0 z_0 z0。如果可解,可以得到一个方程:
x ≡ m 0 z 0 + r 0 ( m o d   l c m ( m 0 , m 1 ) ) x\equiv{m_0z_0+r_0({\rm{mod}}\,lcm(m_0,m_1))} xm0z0+r0(modlcm(m0,m1))
该方程与原方程组等价。其中 l c m lcm lcm为最小公倍数。
如此反复,就可以将线性同余方程组合并为一个方程,并且利用扩展的欧几里德算法求解。在每一步中,均需判断是否有解。

typedef long long int llt;
//to convert two congruence equations to equivalent one
//x = r1 (mod m1)
//x = r2 (mod m2)
//the out put is:  x = r3 (mod m3)
//return true if there is a solution, otherwise false
bool mergeCrt(llt r1,llt m1,llt r2,llt m2,llt&r3,llt&m3){
    llt x,y;
    llt g = exEuclid(m1,m2,x,y);
    llt r = (r2 - r1) % m2;
    if ( r < 0 ) r += m2;

    if ( r % g ) return false;//no solution

    x = r / g * x % ( m2 / g );//the least positive solution

    m3 = m1 / g * m2; //lcm
    r3 = ( ( x * m1 ) % m3 + r1 ) % m3;
    return true;
}

//Chinese remainder theorem to solve linear congruence equations
//n is the count of equations
//remainder is the array of remainders, index from 0
//mod is the array of modules, index from 0
//return the least positive solution or -1 if there is no solution
llt Crt(int n,llt const remainder[],llt const mod[]){
    llt r1 = remainder[0],m1 = mod[0];
    for(int i=1;i<n;++i){
        if ( !mergeCrt(r1,m1,remainder[i],mod[i],r1,m1) ){
            return -1;
        }
    }

    r1 %= m1;
    if ( r1 < 0 ) r1 += m1;
    return r1;
}

完整的程序可以见POJ2891

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值