中国剩余定理

描述

问题描述

回到梦开始的地方:

有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

不过评测寄可读不懂古文,我们给出形式化的问题描述:

给定下列线性同余方程组:

{xr1(modm1)xr2(modm2)xrn(modmn)\begin{cases}x \equiv r_1 (\operatorname{mod} m_1)\\x \equiv r_2 (\operatorname{mod} m_2)\\\dots\\x \equiv r_n (\operatorname{mod} m_n)\end{cases}

mm 两两互素。

求解 xx

定理描述

  • M=i=1nmi,pi=M/riM = \prod\limits_{i=1}^{n}m_i,p_i=M/r_i

  • qiq_i 表示 pip_i 的乘法逆元。

  • 则其通解的形式为:

    x=i=1npiqiri+kM,(kZ)x=\sum\limits_{i=1}^{n}p_iq_ir_i+kM,(k\in\mathbb{Z})

证明

显然地,由于 mim_i 互素,则 mim_ipip_i 互素。

这说明 pip_i 在模 mim_i 意义下乘法逆元必存在。

自然地:

piqiriri(modmi)p_iq_ir_i \equiv r_i (\operatorname{mod} m_i)

显然地:

j{N[1,n]i},pjqjrj0(modmi)\forall j\in \{\mathbb{N} \cap [1,n]-i\}, p_jq_jr_j \equiv 0 (\operatorname{mod} m_i)

所以 xjipjqjrj+piqiri0+riri(modmi)x \equiv \sum\limits_{j\not=i}p_jq_jr_j+p_iq_ir_i \equiv \sum0+r_i\equiv r_i (\operatorname{mod} m_i)

xx 为一个合法解。

若另一合法解为 x:x^\prime:

xx0(modmi)x^\prime-x\equiv0(\operatorname{mod} m_i)

mim_i 互素,这说明 MxxM \mid x^\prime-x,故方程任意两解间必相差 MM 的整数倍,定理得证。

k=0k=0x=xminx=x_{\operatorname{min}}

代码实现

实现难度不高,要注意的是乘法逆元在不同题目中的处理方式,对于洛谷模板,我们用 exgcd\operatorname{exgcd} 求解(模数互素)。

namespace CRT {
const int N = 10004;
int n;
typedef long long vType;
vType r[N], m[N], M;
void init(int _n, int *_r, int *_m) {
n = _n;
m = 1;
for (int i=1; i<=n; i++) {
m[i] = _m[i];
r[i] = _r[i];
M *= m[i];
}
}
void exgcd(vType a, vType b, vType &x, vType &y) {
if (!b) {
x=1;y=0;
return ;
}
vType xx, yy;
exgcd(y, x%y, xx, yy);
x = yy;
y = xx - (a/b)*yy;
}
vType solve() {
vType ans = 0;
for (int i=1; i<=n; i++) {
vType p=M/r[i], q, tmp;
exgcd(p,m[i],q,tmp);
if (q<0) q += M;
ans = (ans + ((p*q)%M*r[i])%M)%M;
}
ans %= M;
if (ans < 0) ans += M;
return ans;
}
}

本来想在 exgcd 那里夹带私货的

后记

上次在知乎上看到了一篇优美的抽象代数证明,不过菜狗不会,有机会再补。