中国剩余定理&扩展中国剩余定理
创建时间:2025-05-28
中国剩余定理
中国剩余定理(Chinese Remainder Theorem,CRT),是数论中的重要定理,但使用场景很有限,且复杂度也只是与扩展中国剩余定理持平,故在OI赛场上用的很少,只需要掌握扩展中国剩余定理即可。当然,中国剩余定理的原理也值得了解。
给定 \(n\) 个形如 \(x \equiv b_i \pmod m_i\) 的方程(\(m_i\) 两两互质),中国剩余定理可以在 \(O(n \log n)\) 的时间内求出 \(x\) 的最小非负数解。
可以考虑先解出这 \(n\) 个同于方程组的解:
令 \(x=\sum x_i\),则 \(x\) 满足
所以 \(x=\sum x_i\) 就是我们原同于方程组的解,至于最小非负整数解,根据同于方程的解的周期性,它就等于 \(x \bmod \textup{lcm}(m_1,m_2,\cdots,m_n)=x \bmod \Pi m_i\)。
接下来考虑怎么解这个方程组:
由于 \(x_i\) 是 \(m_1,m_2,\cdots,m_{i-1},m_{i+1},\cdots,m_n\) 的倍数,所以 \(x_i\) 一定可以写作 \(k \cdot \textup{lcm}(m_1,m_2,\cdots,m_{i-1},m_{i+1},\cdots,m_n)=k_i \frac {\Pi m_j} {m_i}\),于是 \(k_i \frac {\Pi m_j} {m_i} \equiv b_i \pmod {m_i}\),这个方程我们就熟悉了,令 \(k_i\equiv (\frac {\Pi m_j} {m_i})^{-1}b_i \pmod {m_i}\) 即可,故 \(x_i\equiv \frac {\Pi m_j} {m_i} {m_i}^{-1}b_i \pmod {m_i}\)。最终答案 \(x=\sum \frac {\Pi m_j} {m_i} {m_i}^{-1}b_i \bmod \Pi m_j\)。
代码:
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int x0, y0, d = exgcd(b, a % b, x0, y0);
x = y0, y = x0 - a / b * y0;
return d;
}
int CRT(int n, const int m[], const int b[]) {
int M = 1, ans = 0;
for (int i = 1; i <= n; i++)
M *= m[i];
for (int i = 1; i <= n; i++) {
int x, y, d = exgcd(M / m[i], m[i], x, y);
ans = (ans + M / m[i] * x % M * b[i]) % M;
}
return (ans + M) % M;
}
扩展中国剩余定理
扩展中国剩余定理(extended Chinese Remainder Theorem,exCRT)可以在 \(m_i\) 不两两互质的情况下求解同于方程,它的本质其实是递推+扩展欧几里得算法。
我们先考虑前 \(i\) 个式子,设 \(ans\) 为前 \(i\) 个式子的最小非负整数解,\(lcm\) 为前 \(m_1,m_2,...,m_i\) 的最小公倍数。由同余方程周期性知前 \(i-1\) 个通解为 \(ans + k \cdot lcm(k \in \N)\),要使第 \(i\) 个同于方程成立,则要求出最小的非负整数 \(x\) 使 \(ans+x \cdot lcm \equiv b_i (\bmod m_i)\),即 \(x \cdot lcm \equiv b_i-ans(\bmod m_i)\)。这个式子我们很熟悉,第一时间就能想到用扩展欧几里得求解该式的变形(\(lcm \cdot x + m_i \cdot y = b_i-ans\))的最小非负整数解,并更新 \(ans \leftarrow ans+x \cdot lcm\),\(lcm \leftarrow \frac {lcm \cdot m_i} d\)。
考虑该递推式的初始状态,即 \(i=0\) 时 \(ans\) 和 \(lcm\) 的值,显然此时解没有任何限制,故 \(ans \leftarrow 0\),\(lcm \leftarrow 1\)。
参考代码:
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
int x0, y0, d = exgcd(b, a % b, x0, y0);
x = y0, y = x0 - a / b * y0;
return d;
}
int exCRT(int n, const int m[], const int b[]) {
int ans = 0, lcm = 1;
for (int i = 1; i <= n; i++) {
int c = ((b[i] - ans) % m[i] + m[i]) % m[i];
int x, y, d = exgcd(lcm, m[i], x, y);
if (c % d)
return -1;
int p = m[i] / d;
x = (x * (c / d) % p + p) % p;
ans += x * lcm, lcm *= m[i] / d;
}
return ans;
}
中国剩余定理&扩展中国剩余定理的应用
P1495 【模板】中国剩余定理(CRT)/ 曹冲养猪;
P4777 【模板】扩展中国剩余定理(EXCRT);
P4774 [NOI2018] 屠龙勇士(平衡树+扩展中国剩余定理);
P4621 [COCI 2012/2013 #6] BAKTERIJE(模拟+枚举+扩展中国剩余定理);
P2480 [SDOI2010] 古代猪文(欧拉定理+质因数+卢卡斯定理+中国剩余定理)。

浙公网安备 33010602011771号