Day 27 - 欧几里得算法与中国剩余定理

1|0欧几里得定理

前面写过了。

2|0中国剩余定理

2|1引入

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

即求满足以下条件的整数:除以 32,除以 53,除以 72

该问题最早见于《孙子算经》中,并有该问题的具体解法。宋朝数学家秦九韶于 1247 年《数书九章》卷一、二《大衍类》对「物不知数」问题做出了完整系统的解答。上面具体问题的解答口诀由明朝数学家程大位在《算法统宗》中给出:

三人同行七十希,五树梅花廿一支,七子团圆正半月,除百零五便得知。

2×70+3×21+2×15=233=2×105+23,故答案为 23

2|2定义

中国剩余定理 (Chinese Remainder Theorem, CRT) 可求解如下形式的一元线性同余方程组(其中 n1,n2,,nk 两两互质):

{xa1(modn1)xa2(modn2)xak(modnk)

上面的「物不知数」问题就是一元线性同余方程组的一个实例。

2|3过程

  1. 计算所有模数的积 n
  2. 对于第 i 个方程:
    1. 计算 mi=nni
    2. 计算 mi 在模 ni 意义下的逆元 mi1
    3. 计算 ci=mimi1不要对 ni 取模)。
  3. 方程组在模 n 意义下的唯一解为:x=i=1kaici(modn)

2|4实现

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; }

2|5证明

我们需要证明上面算法计算所得的 x 对于任意 i=1,2,,k 满足 xai(modni)

ij 时,有 mj0(modni),故 cjmj0(modni)。又有 cimi(mi1modni)1(modni),所以我们有:

xj=1kajcj(modni)aici(modni)aimi(mi1modni)(modni)ai(modni)

即对于任意 i=1,2,,k,上面算法得到的 x 总是满足 xai(modni),即证明了解同余方程组的算法的正确性。

因为我们没有对输入的 ai 作特殊限制,所以任何一组输入 {ai} 都对应一个解 x

另外,若 xy,则总存在 i 使得 xy 在模 ni 下不同余。

故系数列表 {ai} 与解 x 之间是一一映射关系,方程组总是有唯一解。

2|6解释

下面演示 CRT 如何解「物不知数」问题。

  1. n=3×5×7=105
  2. 三人同行 七十 希:n1=3,m1=n/n1=35,m112(mod3),故 c1=35×2=70
  3. 五树梅花 廿一 支:n2=5,m2=n/n2=21,m211(mod5),故 c2=21×1=21
  4. 七子团圆正 半月n3=7,m3=n/n3=15,m311(mod7),故 c3=15×1=15
  5. 所以方程组的唯一解为 x2×70+3×21+2×1523323(mod105)。(除 百零五 便得知)

2|7Garner 算法

CRT 的另一个用途是用一组比较小的质数表示一个大的整数。

例如,若 a 满足如下线性方程组,且 a<i=1kpi(其中 pi 为质数):

{aa1(modp1)aa2(modp2)aak(modpk)

我们可以用以下形式的式子(称作 a 的混合基数表示)表示 a

a=x1+x2p1+x3p1p2++xkp1pk1

Garner 算法 将用来计算系数 x1,,xk

rijpi 在模 pj 意义下的逆:

piri,j1(modpj)

a 代入我们得到的第一个方程:

a1x1(modp1)

代入第二个方程得出:

a2x1+x2p1(modp2)

方程两边减 x1,除 p1 后得

a2x1x2p1(modp2)(a2x1)r1,2x2(modp2)x2(a2x1)r1,2(modp2)

类似地,我们可以得到:

xk=(((akx1)r1,kx2)r2,k))rk1,kmodpk

实现:

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]; } }

该算法的时间复杂度为 O(k2)。实际上 Garner 算法并不要求模数为质数,只要求模数两两互质,我们有如下伪代码:

Chinese Remainder Algorithm cra(v,m):Inputm=(m0,m1,,mn1)miZ+gcd(mi,mj)=1 for all ij,v=(v0,,vn1) where vi=xmodmi.Outputxmodi=0n1mi.1for i from 1 to (n1) do2Ci(j=0i1mj)1modmi3xv04for i from 1 to (n1) do5u(vix)Cimodmi6xx+uj=0i1mj7return (x)

可以发现在第六行中的计算过程对应上述混合基数的表示。

2|8应用

某些计数问题或数论问题出于加长代码、增加难度、或者是一些其他原因,给出的模数:不是质数

但是对其质因数分解会发现它没有平方因子,也就是该模数是由一些不重复的质数相乘得到。

那么我们可以分别对这些模数进行计算,最后用 CRT 合并答案。

下面这道题就是一个不错的例子。

洛谷 P2480 [SDOI2010] 古代猪文

给出 G,n1G,n109),求:

Gkn(nk)mod999 911 659

首先,当 G=999 911 659 时,所求显然为 0

否则,根据欧拉定理,可知所求为:

Gkn(nk)mod999 911 658mod999 911 659

现在考虑如何计算:

kn(nk)mod999 911 658

因为 999 911 658 不是质数,无法保证 x[1,999 911 657]x 都有逆元存在,上面这个式子我们无法直接计算。

注意到 999 911 658=2×3×4679×35617,其中每个质因子的最高次数均为一,我们可以考虑分别求出 kn(nk) 在模 23467935617 这几个质数下的结果,最后用中国剩余定理来合并答案。

也就是说,我们实际上要求下面一个线性方程组的解:

{xa1(mod2)xa2(mod3)xa3(mod4679)xa4(mod35617)

而计算一个组合数对较小的质数取模后的结果,可以利用卢卡斯定理。

2|9扩展:模数不互质的情况

1|0两个方程

设两个方程分别是 xa1(modm1)xa2(modm2)

将它们转化为不定方程:x=m1p+a1=m2q+a2,其中 p,q 是整数,则有 m1pm2q=a2a1

由裴蜀定理,当 a2a1 不能被 gcd(m1,m2) 整除时,无解;

其他情况下,可以通过扩展欧几里得算法解出来一组可行解 (p,q)

则原来的两方程组成的模方程组的解为 xb(modM),其中 b=m1p+a1M=lcm(m1,m2)

1|0多个方程

用上面的方法两两合并即可。

2|10习题

本页面部分内容译自博文 Китайская теорема об остатках 与其英文翻译版 Chinese Remainder Theorem。其中俄文版版权协议为 Public Domain + Leave a Link;英文版版权协议为 CC-BY-SA 4.0。


__EOF__

本文作者So_noSlack
本文链接https://www.cnblogs.com/So-noSlack/p/18340005.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   So_noSlack  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示