【算法学习笔记】模运算总结

模运算是一个高深的地方,初来乍到,还是写一下为敬QAQ。。。

记号

我们把 a 除以 m 所得的余数记作 amodm
如果 amodm=bmodm,即 a, b 除以 m 所得的余数相等,那么我们记作:

ab(modm)

基本性质

模运算有一些基本性质:如果 ab(modm) 且有 cd(modm),那么下面的模运算律成立:

a+cb+d(modm)acbd(modm)a×cb×d(modm)

这就是我们平常经常利用的性质,如果答案对一个数取模,那么模了再加,乘,减都是不影响答案的。特别注意除法是没有这个性质的!

剩余系

如果一个剩余系中包含了这个正整数 n 所有可能的余数(一般地,对于任意正整数 n,有 n 个余数:0,1,2,...,n1),那么就被称为是模 n 的一个完全剩余系,记作 Zn;而简化剩余系就是完全剩余系中与 n 互素的数的那些元素,记作 Zn

Zn 里面的每一个元素代表所有模 n 意义下与它同余的整数。例如 n=5 时,Z5 的元素 3 实际上代表了 3,8,13,18,....,5k+3(kN) 这些模 53 的数。 我们把满足同余关系的所有整数看作一个同余等价类

自然地,在 Zn 中的加法,减法,乘法,结果全部要在模 n 意义下面了,例如在 Z5 中,3+2=0,3×2=1

逆元

在实数运算下面,如果 ab=1,那么可以说a,b 互为倒数,它们相乘永远得 1。不幸的是,modm 的运算下面也有倒数的概念,而且要恐怖的多。

如果在 Zn 中两元素 a,b 满足 ab=1 ,比如在 Z15 中,713=1,那么我们就说 a,b 互为模 n 意义下乘法的逆 !记作 a=b1,b=a1

我们知道,除以一个数等价于乘以这个数的倒数,在模运算中,除以一个数等于乘上这个数的逆(如果这个数存在乘法逆的话)!举个栗子,在 Z5 中, 4÷3=4×31=4×2=3

看上去有点神乎其神,4÷3 甚至不是整数,怎么可能答案是 3 ???别忘了,剩余系中每一个元素都对应一个同余等价类,所以 4÷3=3 的实际含义是:“假定有两个整数 a,b 满足 ab 是整数且a,b 除以 5 的余数分别是 43 ,那么 ab 除以 5 的余数等于 3 ” ,比如 a=9,b=3 时就成立。

线性模方程

线性模方程是下面这玩意,其中 x 是未知数,我们需要做的事情是求出 xZm 的解集。

axb(modm)

因为同余,所以有 axb=ym ,即 axmy=b ,这个方程有解当且仅当 gcd(a,m)|b 。这是第一步。

假设 a 的逆在模 m 意义下存在,为 a1 ,那么根据基本性质,两边可以同乘 a1 ,则得到 xb×a1(modm) ,是不是这样,问题就轻松解决了呢?并不是,a 的逆极有可能在模 m 意义下不存在,我们试着求一下在模 m 意义下 a 的逆。即解

ax1(modm)

转化

ax1=my

移项

axmy=1

根据扩展欧几里得算法,当且仅当 gcd(a,m)=1 ,模 m 意义下 a 的逆存在。所以,我们要解 axb(modm) ,必须将其转化,使得 a 的乘法逆存在。

axmy=b 两边同时除以 gcd(a,m) ,得到:

axmy=b(a=agcd(a,m),m=mgcd(a,m),b=bgcd(a,m))

于是问题回到了求解:

axb (mod m)

这一回,我们能保证 gcd(a,m)=1 ,所以 a 在这里一定有乘法逆!

那么这个方程的解是在 Zm 剩余系内的:

x(a)1b (mod m)

但是我们需要求解的是 Zm 剩余系内的元素,怎么转换过去呢?设 p=(a)1b ,那么我们有无穷多个实数解:x=p,p+m,p+2m,p+3m... 。我们想要知道,这无穷多个实数解,在模 m 意义下究竟有多少个等价类(即模 n 会有多少个不同的余数)?大家可能已经发现了,正好 d=gcd(a,m) 个,分别为 p,p+m,p+2m,...,p+(d1)m

为什么呢?假设 p+imp+jmm 同余,那么 (p+im)(p+jm)=(ij)m,必定是 m的倍数,也就是 ijd 的倍数。所以是 d 个一轮回的!

p,p+dm,p+2dm,... 这些数模 m 同余;
p+m,p+(d+1)m,p+(2d+1)m,...这些数模 m 同余;
...
p+(d1)m,p+(d+d1)m,p+(2d+d1)m,... 这些数模 mm 同余;

p,p+m,p+2m,...,p+(d1)m 之间不可能同余,因为不满足 ijd 的倍数。所以,方程 axb(modm) 要么无解,要么恰有 gcd(a,m) 个解。

总结起来,解线性同余方程只需要求 a 的乘法逆,但分析过程还是有些恼人的。

中国剩余定理

更加详细的介绍:Here

现在如果有多个同余方程,即同余方程组,变量只有一个,且 x 前面系数为 1, 任意 mi 之间互素,该怎么做呢?
中国剩余定理在这里派上用场了,它并不是一种算法,而是一种思考、构造的方法。

现在有方程组 xai(modmi)。我们令 M=miwi=Mmi。那么解一定可以表示为ZM 剩余系中的一个元素,即 xb(modM)。我们来构造这个解。

由于 mi 之间互素,可以得到 gcd(mi,wi)=1,构造出这样一个方程 wipi+miqi=1,由于 gcd(mi,wi)=1,此方程一定有解。用扩展欧几里得算法解出 pi,qi,令 ei=wipi,现在有一些有趣的性质,方程两边都模 mi,得到 eimodmi+0=1eimodmi=1

依据这一性质,我们构造得到方程在 ZM 剩余系中的唯一解 xe1a1+e2a2+...+enan(modM)。验证一下,只需把每个方程带进去,看是否都成立即可。对于 xai(modmi),将得到的解右边模 mi,惊奇的发现,除了 eiai 这一项的结果为 ai 之外,其余项的结果都是 0

x0+0+..+1×ai+0+..+0(modmi)

原因是 eimodmi=1 一模变成 1,还有 中 wj 必定含有因子 mi,所以一模就成 0 了。

则对于每一个 mi,我们都能得到一个与原方程组一模一样的同余等式,所以这个解是正确的。

所以 x0=e1a1+e2a2+...+enan 显然是一个实数解,x0+M,x0+2M,x0+3M....x 都是解,原方程组有无穷组实数解。

欧拉定理

在数论中,欧拉定理是一个关于同余的性质。欧拉定理表明,若 n,a 为正整数,且 n,a 互素,则:

aφ(n)1(modn)

特别的,当 n 为素数的时候,aa 可取任意 Zn 内元素。由于 φ(n)=n1,故有:

an11(modn)ana(modn)

这就是费马小定理。观察到右边 1 的存在,发现与之前所说的逆元有一点相似:

ax1(modn)

x 是逆元,根据费马小定理,有 xan2(modn),故可以快速幂在 O(logn) 的时间内快速求出任意 Zn 内元素的逆元,但只有在 n 是素数的时候才起作用。

离散对数

n 为素数的时候,解模方程:

axb(modn)

如果是实数范围内,答案是 logab,可惜并不是,这里采用一种精妙的解决办法。
解:根据欧拉定理有:an11(modn),又 a01(modn),所以 ax 在模 n 剩余系内的值无限循环,以 a0,a1,...,an2 为循环节。
所以,只需检查 x=0,1,2,...,n2 时是不是解即可。但这样复杂度是 O(n) 的,下面用一种构造手段将复杂度降下来:
我们先检查前 m 项(m 取值稍后说明),即 a0,a1,...,am1n 的值是否为 b,并把 aimodn 的值保存在 ei 中,求出 amam

下面接着考虑 am,am+1,...,a2m1,这次不需要检查,如果他们当中存在解,说明存在 i(0i<m) 使得 eiamb(modn)。两边乘 am,得到 eibam(modn),也就是说我们只需要检查有没有一个 i,使得 eibam(modn),这相当于依次检查了 am,am+1,...,a2m1

如果仍然没有检查到解,这回考虑 a2m,a2m+1,...,a3m1,同样的,我们只需要检查有没有一个 i,使得 eib(am)2(modn),这相当于依次检查了 a2m,a2m+1,...,a3m1

显然使用 STL 中的 MAP 可以帮我们快速完成检测操作。预处理出 ei 的复杂度是 O(mlogm),求出 am 的复杂度是 logn,一共有 n/m 轮检测,每轮复杂度 logm。总复杂度 O((m+nm)logm) ,当 m=n 时,复杂度最低为:O(nlogn)

指数循环节

axb(modn)

x 大到一定程度的时候,我们没有办法算 b 了,这时需要用到指数循环节。
如果 gcd(a,n)=1,由欧拉定理 aφ(n)1(modn) 可知指数以 [0,φ(n)1] 为循环节不断循环,故有

axaxmodφ(n)(modn)

如果 gcd(a,n)1 ,似乎不好做了,不过也有公式!

axaxmodφ(n)+φ(n)(modn)(xφ(n))

需要声明一下,只有 xφ(n) 时此公式成立,所以千万不要盲目的取余了再加!

关于 gcd(a,n)1 的公式参考:Here

posted @   RioTian  阅读(3895)  评论(0编辑  收藏  举报
编辑推荐:
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
阅读排行:
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 5. Nginx 负载均衡配置案例(附有详细截图说明++)
历史上的今天:
2020-07-30 (转)Github+jsDelivr+PicGo 打造稳定快速、高效免费图床
2020-07-30 解决Github中使用Octotree时,出现 Error: API limit exceeded 报错 或者 Error: Connection error报错的问题(详细操作)
2020-07-30 P3372 【模板】线段树 1
2020-07-30 【题解】Qin Shi Huang's National Road System HDU - 4081 ⭐⭐⭐⭐ 【次小生成树】
点击右上角即可分享
微信分享提示

📖目录