中国剩余定理

前面我们已经学习了求解单个线性模方程,如果有多个方程,变量还是只有一个,该怎么办呢?

可以考虑用中国剩余定理(Chinese Remainder Theorem)。假定有方程组$x\equiv a_i(mod \ m_i)$,且所有模$m_i$两两互素。令$M$为所有$m_i$的乘积,$w_i=M/m_i$,则$(w_i,mi)=1$。用扩展欧几里得算法可以找到$p_i$和$q_i$使得$w_i p_i + m_i q_i = 1$。然后令$e_i = w_i p_i$,则方程组等价于单个方程$x\equiv e_1 a_1 + e_2 a_2 + \cdots + e_n a_n(mod \ M)$.换句话说,在模M的剩余系下,原方程组有唯一解。

      不难验证$x=  e_1 a_1 + e_2 a_2 + \cdots + e_n a_n$是一个解(具体见拉格朗日插值法),把等式$w_i p_i + m_i q_i = 1$两边模$m_i$后立即可得到$e_i \ mod\ m_i = 1$,而对于不等于$i$的$j$,$w_i$是$m_j$的倍数(想一想,为什么),因此$e_i \ mod\ m_j = 0$。这样,$x_0$对$m_i$取模时,除了$e_i a_i$这一项余数为$ 1 \times a_i = a_i$之外,其余项的余数均为0.代码如下:

//n个方程:x=a[i](mod m[i])
ll china(int n, int* a, int* m)
{
    ll M = 1, d, y, x = 0;
    for (int i = 0; i < n; i++)  M *= m[i];
    for (int i = 0; i < n; i++)
    {
        ll w = M / m[i];
        exgcd(m[i], w, d, d, y);        //d共用了
        x = (x + y * w * a[i]) % M;   //x相当于sum
    }
    return (x + M) % M;
}

 

posted @ 2019-03-01 10:08  Rogn  阅读(533)  评论(0编辑  收藏  举报