中国剩余定理
若无特殊说明,本章涉及的变量皆为正整数.
简介 #
中国剩余定理最早发现于《孙子算经》中.
有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二. 问物几何?
即求满足下列条件的 $x$:
$$\left\{\begin{aligned} x \bmod 3 = 2 \\ x \bmod 5 = 3 \\ x \bmod 7 = 2 \\ \end{aligned}\right.$$
它的通解公式为 $x=233+105k$.
《孙子算经》中只给出了最小正整数解,也就是 $k=-2$ 时的解:$x=23$.
不过,今天我们只关心中国剩余定理更普遍的应用.
问题 #
中国剩余定理指关于 $x$ 的同余方程组的解法:
$$\left\{\begin{aligned} x&≡a_1 \ (\bmod \ m_1)\\ x&≡a_2 \ (\bmod \ m_2)\\ &\cdots\\ x&≡a_k \ (\bmod \ m_k) \end{aligned}\right.$$
其中 $a_1, a_2, \cdots, a_k$ 两两互质.
解法 #
设 $M=\prod^k_{i=1}m_i$.
设 $ M_i=\frac{M}{m_i}$,即除 $m_i$ 外,其余所有 $m$ 的乘积.
设 $M_it_i≡1\pmod{m_i}$,$t_i$ 为 $M_i$ 关于模 $m_i$ 的 乘法逆元.
利用以上数据可以构造一个解:
$$\begin{aligned} x= \ &a_1M_1t_1 + a_2M_2t_2 + a_3M_3t_3 + \cdots + a_kM_kt_k\\ = \ &\sum^k_{i=1}a_iM_it_i \end{aligned}$$
其正确性显然.
模板 #
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 16;
LL n, a[N], m[N], M[N], prodM = 1, ansX;
void exGcd(int a, int b, int &x, int &y) {
if (b == 0) { x = 1, y = 0; return; }
exGcd(b, a % b, x, y);
int t = x; x = y, y = t - a / b * y;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> a[i] >> m[i];
prodM *= m[i];
}
for (int i = 1; i <= n; i ++) {
M[i] = prodM / m[i];
LL x = 0, y = 0;
exGcd(M[i], m[i], x, y);
ansX += a[i] * M[i] * (x + m[i]) % m[i];
}
cout << ansX % prodM;
return 0;
}