中国剩余定理(Chinese Remainder Theorem)详解:从原理到代码实现
在数论和计算机科学中,中国剩余定理(CRT)是一种处理多个模运算方程组的强大工具,它不仅用于解线性同余方程组,还广泛应用于密码学、RSA算法、信号处理等领域。本文将从原理讲起,结合例子逐步深入,并提供可运行的代码实现。
一、什么是中国剩余定理?
中国剩余定理是关于整数同余方程组求解的一条基本定理,它的基本形式如下:
定理表述:
设有 k k k 个整数模数 m 1 , m 2 , … , m k m_1, m_2, \dots, m_k m1,m2,…,mk,它们两两互素,即 gcd ( m i , m j ) = 1 , ∀ i ≠ j \gcd(m_i, m_j) = 1, \forall i \neq j gcd(mi,mj)=1,∀i=j,给定如下方程组:
{ x ≡ a 1 ( m o d m 1 ) x ≡ a 2 ( m o d m 2 ) ⋮ x ≡ a k ( m o d m k ) \begin{cases} x \equiv a_1 \pmod{m_1} \\ x \equiv a_2 \pmod{m_2} \\ \vdots \\ x \equiv a_k \pmod{m_k} \end{cases} ⎩ ⎨ ⎧x≡a1(modm1)x≡a2(modm2)⋮x≡ak(modmk)
则该方程组有唯一解 ( m o d M ) \pmod{M} (modM),其中 M = m 1 ⋅ m 2 ⋯ m k M = m_1 \cdot m_2 \cdots m_k M=m1⋅m2⋯mk。
二、逆元
对于整数 a a a 和 m m m,如果存在一个整数 x x x,使得:
a ⋅ x ≡ 1 ( m o d m ) a \cdot x \equiv 1 \pmod{m} a⋅x≡1(modm)
那么我们称 x x x 是 a a a 在模 m m m 意义下的乘法逆元(modular inverse),记作:
x = a − 1 ( m o d m ) x = a^{-1} \pmod{m} x=a−1(modm)
2.1 存在条件:
当且仅当 gcd ( a , m ) = 1 \gcd(a, m) = 1 gcd(a,m)=1,也就是 a a a 与 m m m 互素时, a a a 才有模 m m m 下的逆元。
2.2 逆元的计算:(扩展欧几里得)
欧几里得算法用于求最大公约数 g c d ( a , b ) gcd(a, b) gcd(a,b),扩展版本则还能找到整数解 ( x , y ) (x, y) (x,y),满足:
a x + b y = gcd ( a , b ) a x + b y = \gcd(a, b) ax+by=gcd(a,b)
当 g c d ( a , m ) = 1 gcd(a, m) = 1 gcd(a,m)=1 时,我们可以得到一组 x , y x, y x,y 使:
a x + m y = 1 ⇒ a x ≡ 1 ( m o d m ) a x + m y = 1 \Rightarrow a x \equiv 1 \pmod{m} ax+my=1⇒ax≡1(modm)
所以 x x x 就是 a a a 的模 m m m 逆元。
2.3 代码求解逆元的实现(python为例)
def extended_gcd(a, b):if b == 0:return a, 1, 0d, x1, y1 = extended_gcd(b, a % b)x, y = y1, x1 - (a // b) * y1return d, x, y# 逆元求解
def mod_inverse(a, m):d, x, _ = extended_gcd(a, m)if d != 1:raise Exception("逆元不存在")return x % m
三、基本思想
设 M = m 1 m 2 ⋯ m k M = m_1 m_2 \cdots m_k M=m1m2⋯mk,令 M i = M m i M_i = \dfrac{M}{m_i} Mi=miM,然后我们找到 y i y_i yi,使得:
M i ⋅ y i ≡ 1 ( m o d m i ) M_i \cdot y_i \equiv 1 \pmod{m_i} Mi⋅yi≡1(modmi)
即 y i y_i yi 是 M i M_i Mi 模 m i m_i mi 的乘法逆元。
最终解为:
x ≡ ∑ i = 1 k a i ⋅ M i ⋅ y i ( m o d M ) x \equiv \sum_{i=1}^k a_i \cdot M_i \cdot y_i \pmod{M} x≡∑i=1kai⋅Mi⋅yi(modM)
三、通俗例子
🌰 例子 1:
解如下方程组:
{ x ≡ 2 ( m o d 3 ) x ≡ 3 ( m o d 5 ) x ≡ 2 ( m o d 7 ) \begin{cases} x \equiv 2 \pmod{3} \\ x \equiv 3 \pmod{5} \\ x \equiv 2 \pmod{7} \end{cases} ⎩ ⎨ ⎧x≡2(mod3)x≡3(mod5)x≡2(mod7)
- M = 3 ⋅ 5 ⋅ 7 = 105 M = 3 \cdot 5 \cdot 7 = 105 M=3⋅5⋅7=105
- M 1 = 105 / 3 = 35 M_1 = 105/3 = 35 M1=105/3=35,求 y 1 y_1 y1 使 35 y 1 ≡ 1 ( m o d 3 ) ⇒ y 1 = 2 35y_1 \equiv 1 \pmod{3} \Rightarrow y_1 = 2 35y1≡1(mod3)⇒y1=2
- M 2 = 105 / 5 = 21 M_2 = 105/5 = 21 M2=105/5=21, 21 y 2 ≡ 1 ( m o d 5 ) ⇒ y 2 = 1 21y_2 \equiv 1 \pmod{5} \Rightarrow y_2 = 1 21y2≡1(mod5)⇒y2=1
- M 3 = 105 / 7 = 15 M_3 = 105/7 = 15 M3=105/7=15, 15 y 3 ≡ 1 ( m o d 7 ) ⇒ y 3 = 1 15y_3 \equiv 1 \pmod{7} \Rightarrow y_3 = 1 15y3≡1(mod7)⇒y3=1
带入公式:
x = 2 ⋅ 35 ⋅ 2 + 3 ⋅ 21 ⋅ 1 + 2 ⋅ 15 ⋅ 1 = 140 + 63 + 30 = 233 ⇒ x ≡ 233 ( m o d 105 ) ⇒ x = 233 m o d 105 = 23 x = 2 \cdot 35 \cdot 2 + 3 \cdot 21 \cdot 1 + 2 \cdot 15 \cdot 1 = 140 + 63 + 30 = 233 \Rightarrow x \equiv 233 \pmod{105} \Rightarrow \boxed{x = 233 \bmod{105} = 23} x=2⋅35⋅2+3⋅21⋅1+2⋅15⋅1=140+63+30=233⇒x≡233(mod105)⇒x=233mod105=23
四、Python代码实现
def extended_gcd(a, b):if b == 0:return a, 1, 0d, x, y = extended_gcd(b, a % b)return d, y, x - (a // b) * ydef mod_inverse(a, m):d, x, _ = extended_gcd(a, m)if d != 1:raise Exception("逆元不存在")return x % mdef chinese_remainder(a_list, m_list):assert len(a_list) == len(m_list)M = 1for m in m_list:M *= mresult = 0for ai, mi in zip(a_list, m_list):Mi = M // miyi = mod_inverse(Mi, mi)result += ai * Mi * yireturn result % M
✅ 使用示例:
a = [2, 3, 2]
m = [3, 5, 7]
x = chinese_remainder(a, m)
print(f"x = {x}") # 输出 x = 23
五、应用场景
- 密码学:RSA解密加速
- 并行计算:多个核分别处理模运算再合并
- 编码理论:错误检测与纠正
- 图灵奖得主姚期智的多方安全计算中也广泛用到CRT
六、常见注意点
- 所有模数必须两两互素;
- 若不互素也可以用扩展版本的中国剩余定理,但解不唯一;
- 逆元必须存在,即 gcd ( M i , m i ) = 1 \gcd(M_i, m_i) = 1 gcd(Mi,mi)=1;
- 计算量大时注意整数溢出,可以用 Python 的大整数或语言自带库。
七、练习题推荐
练手编程题:洛谷P1495 中国剩余定理