「学习笔记」中国剩余定理

定义

中国剩余定理(Chinese Remainder Theorem,CRT),可用于求解如下形式的一元线性同余方程组(其中 $a_1,a_2,…,a_3$ 两两互质 ):

$$\begin{cases} x \equiv a_1\ ({\rm mod}\ n_1) \ x\equiv a_2\ ({\rm mod}\ n_2) \ … \ x \equiv a_k\ ({\rm mod}\ n_k)\end{cases}$$

(我习惯看成 $a \equiv c\ ({\rm mod}\ b)$ ,即 $a\%b=c$ )

解法

  • 先求出模数的积 $N$ ,设 $N=\prod_{i=1}^k n_i$

  • 对于第 $i$ 个方程:

    • 先求除了 $n_i$ 外的所有模数之积,设 $N_i=\frac{N}{n_i}$
    • 求 $N_i$ 在模 $n_i$ 意义下的逆元 $N_i^{-1}$ ,即 $N_i\times N_i^{-1} \equiv 1\ ({\rm mod}\ n_i)$
  • 最小正整数解 $x=\sum_{i=1}^k a_i\times N_i\times N_i^{-1}$

证明

对于第 $i$ 个方程:

  • 当 $i\not = j$ 时,有 $a_j\times N_j\times N_j^{-1} \equiv 0\ ({\rm mod}\ n_i)$ ,因为 $N_j$ 中必然有 $n_i$ 。
  • 当 $i=j$ 时,有$a_i\times N_i\times N_i^{-1} \equiv a_i\ ({\rm mod}\ n_i)$ 。

因此,$\sum_{i=1}^k a_i\times N_i\times N_i^{-1}\equiv a_i\ ({\rm mod}\ n_i)$ 。

实现

ll CRT() {
    ll s = 1, ans = 0;
    for (int i = 1; i <= n; i++)s *= b[i];
    for (int i = 1; i <= n; i++) {
        ll x, y, r = s / b[i];
        exgcd(r, b[i], x, y);   //求逆元
        (ans += c[i] * r * x) %= s;
    }
    return (ans % s + s) % s;
}

扩展中国剩余定理

定义

$$\begin{cases} x \equiv a_1\ ({\rm mod}\ n_1) \ x\equiv a_2\ ({\rm mod}\ n_2) \ … \ x \equiv a_k\ ({\rm mod}\ n_k)\end{cases}$$

仍然是这个方程组,但此时模数不互质了。

解法和证明

由于模数不互质,$N_i$ 与 $n_i$ 也不互质,则不存在 $N_i$ 的逆元。此时再用原算法算就不对了。

于是可以考虑换一种方法,基本想法就是考虑将两个同余方程合并为一个,依次求解。

$$\begin{cases} x \equiv a_1\ ({\rm mod}\ n_1) \ x\equiv a_2\ ({\rm mod}\ n_2) \ \end{cases}$$

对于这两个方程,我们可以把它写成:

$$ x=k_1 n_1+a_1=k_2 n_2+a_2 $$

移项一下,有:

$$ k_1n_1-k_2n_2=a_2-a_1 $$

可以发现,式子中只有 $k_1,k_2$ 两个未知数,可以用扩展欧几里得算法求出 $k_1,k_2$ 一组解:

设 $g=gcd(n_1,n_2)$ ,$k_1′,k_2’$ 为 exgcd 求出的值。

$$\begin{cases} k_1=\frac{k_1′(a_2-a_1)}{g} \ k_2=\frac{k_2′(a_2-a_1)}{g}\ \end{cases}$$

代回原式即可得到方程组的一组特解:

$$x_0=\frac{k_1′(a_2-a_1)}{g}n_1+a_1$$

而方程组的通解即为:

$$x=x_0\ \pm\ K\cdot lcm(n_1\ ,\ n_2)$$

这个式子又等价于这样一个新的方程:

$$x\equiv x_0\ ({\rm mod}\ lcm(n_1,n_2)) $$

这样我们就成功把两个方程合并为一个了。

主要思路就是这样,至于一些更细节的证明,这边建议看模板题题解区,大佬们讲的更好orz。

实现

实现起来有点不太好写,这里的写法借鉴了题解区的大佬的写法。

ll mul(ll n, ll k, ll mod) {    //龟速乘
    ll ans = 0;
    while (k) {
        if (k & 1) ans = (ans + n) % mod;
        k >>= 1;
        n = (n + n) % mod;
    }
    return ans;
}

ll exCRT() {
    ll ans = c[1];
    ll M = b[1];
    for (int i = 2; i <= n; i++) {
        ll x, y, C = ((c[i] - ans) % b[i] + b[i]) % b[i];
        ll g = exgcd(M, b[i], x, y);//求x*b[i-1]-y*b[i]=gcd(b[i-1],b[i])的解
        x = mul(x, C / g, b[i]);    //龟速乘,求原方程x*b[i-1]-y*b[i]=c[i]-c[i-1]的解
        ans += M * x;
        M *= b[i] / g;
        ans = (ans + M) % M;    //更新通解
    }
    return ans;
}
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇