中国剩余定理
引入
「物不知数」问题:有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?
即求满足以下条件的整数:除以
该问题最早见于《孙子算经》中,并有该问题的具体解法。宋朝数学家秦九韶于 1247 年《数书九章》卷一、二《大衍类》对「物不知数」问题做出了完整系统的解答。上面具体问题的解答口诀由明朝数学家程大位在《算法统宗》中给出:
三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五便得知。
定义
中国剩余定理 (Chinese Remainder Theorem, CRT) 可求解如下形式的一元线性同余方程组(其中
上面的「物不知数」问题就是一元线性同余方程组的一个实例。
过程
- 计算所有模数的积
; - 对于第
个方程:- 计算
; - 计算
在模 意义下的 逆元 ; - 计算
(不要对 取模)。
- 计算
- 方程组在模
意义下的唯一解为: 。
实现
=== "C++"
```cpp
LL CRT(int k, LL* a, LL* r) {
LL n = 1, ans = 0;
for (int i = 1; i <= k; i++) n = n * r[i];
for (int i = 1; i <= k; i++) {
LL m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
```
=== "Python"
```python
def CRT(k, a, r):
n = 1; ans = 0
for i in range(1, k + 1):
n = n * r[i]
for i in range(1, k + 1):
m = n // r[i]; b = y = 0
exgcd(m, r[i], b, y) # b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n
return (ans % n + n) % n
```
证明
我们需要证明上面算法计算所得的
当
即对于任意
因为我们没有对输入的
另外,若
故系数列表
解释
下面演示 CRT 如何解「物不知数」问题。
;- 三人同行 七十 希:
,故 ; - 五树梅花 廿一 支:
,故 ; - 七子团圆正 半月:
,故 ; - 所以方程组的唯一解为
。(除 百零五 便得知)
Garner 算法
CRT 的另一个用途是用一组比较小的质数表示一个大的整数。
例如,若
我们可以用以下形式的式子(称作
Garner 算法 将用来计算系数
令
把
代入第二个方程得出:
方程两边减
类似地,我们可以得到:
=== "C++"
```cpp
for (int i = 0; i < k; ++i) {
x[i] = a[i];
for (int j = 0; j < i; ++j) {
x[i] = r[j][i] * (x[i] - x[j]);
x[i] = x[i] % p[i];
if (x[i] < 0) x[i] += p[i];
}
}
```
=== "Python"
```python
for i in range(0, k):
x[i] = a[i]
for j in range(0, i):
x[i] = r[j][i] * (x[i] - x[j])
x[i] = x[i] % p[i]
if (x[i] < 0):
x[i] = x[i] + p[i]
```
该算法的时间复杂度为
可以发现在第六行中的计算过程对应上述混合基数的表示。
应用
某些计数问题或数论问题出于加长代码、增加难度、或者是一些其他原因,给出的模数:不是质数!
但是对其质因数分解会发现它没有平方因子,也就是该模数是由一些不重复的质数相乘得到。
那么我们可以分别对这些模数进行计算,最后用 CRT 合并答案。
下面这道题就是一个不错的例子。
给出
首先,当
否则,根据 欧拉定理,可知所求为:
现在考虑如何计算:
因为
注意到
也就是说,我们实际上要求下面一个线性方程组的解:
而计算一个组合数对较小的质数取模后的结果,可以利用 卢卡斯定理。
扩展:模数不互质的情况
两个方程
设两个方程分别是
将它们转化为不定方程:
由裴蜀定理,当
其他情况下,可以通过扩展欧几里得算法解出来一组可行解
则原来的两方程组成的模方程组的解为
多个方程
用上面的方法两两合并即可。
习题
-
本页面部分内容译自博文 Китайская теорема об остатках 与其英文翻译版 Chinese Remainder Theorem。其中俄文版版权协议为 Public Domain + Leave a Link;英文版版权协议为 CC-BY-SA 4.0。
贡献者:@Imple@Menci@WenzelTian@little-cindy@Baoshuo@hly1204@Xingyu@Great-designer
本页面最近更新:2/3/2023, 12:00:00 AM,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用