关于模运算

前言

写这篇文章的时候,本蒟蒻正在挑战3个月达省一;

之前一直对模运算耿耿于怀十分好奇,遂决定,今天拿下;

最后在正文开始之前放一个搞笑的东西:

关于模运算的定义

我们先定义带余除法 (其实就是除法):
\(设两个数 a,m \in \symbb{Z}, m \not= 0,则a、m的带余除法定义为:\)

存在唯一的整数q、r(r必须大于等于0),使得

\[a = qm+r \]

我们记a模m为: \(a \bmod m\)

我们把 \(q\) 称做商,\(r\) 称做余数(也称a模m的结果),记作:

\[r = a \bmod m \]

关于114514 & 998244353

OI 中,模运算最直接的用处就是解决一些需要处理带模运算的题目;

而 \(114514\) 和 \(998244353\) 这两个神奇的模数就不得不提一下了:

\(114514\) 请自行百度(主要是我也没查出来什么), \(998244353\) 有如下的几个特点:

1.它的二进制表达是:111011100000000000000000000001

2.它是一个质数。

3.它是一个奇数。

4.它可以表达为两个数的平方和:\(998244353 = 3943^2 + 31348^2\)

5.它是勾股数之一:\(998244353^2 = 247210328^2 + 967149855^2\)

6.它可以被表达为:\(998244353 = 7 \times 17 \times 2^{23} + 1\)

7.998244353最优美的性质莫过于它是个完美恶臭数:

\[998244353=( 114514 * ( 54-1+114 * (1+14*5+1+4) ) ) + ( 4+11451 * (4-1-15+14) ) + ( 11+41*54 + (141+541) ) + (4-1-15+14) \]

之所以称为完美,因为每一个括号里114514都出现了正整数次;

Tips :\(998244353\) 最大的一个特点是:出题人 \(99\%\) 的情况下是不会使用这个数的,取而代之的是 \(998234353\) 、\(998244553\) ,不过应该没人会栽在上面

模运算的两个等式

\[\S 1. (a+b) \bmod m = ((a \bmod m)+(b \bmod m)) \bmod m \]

\[\S 2. (a \times b) \bmod m = ((a \bmod m) \times (b \bmod m)) \bmod m \]

这两个是经常会用到的等式,大部分的OI题目都要求取模

但是通常情况下,这时的结果都远远超出了int型的范围,我们需要在运算过程中就直接取模,而这步的正确性就是依赖于上面的两个等式

下面我们来证明一下:

证明1:

依据带余除法,我们设 \(a = q_1m + r_1,\) \(b = q_2m + r_2\),那么带入等式左边,我们有:

\[(a+b)\bmod m = (q_1m+r_1+q_2m+r_2) \bmod m \]

更进一步,合并同类项:

\[原式 = ((q_1+q_2)m+r_1+r_2) \bmod m \]

引入一个定理:

\(a \bmod m\) 的结果与 \((a+k \times m) \bmod m\) 是一样的,通俗来说,就是一个数除以另一个数的余数,与这个数加上任意倍的除数之后除以除数的余数是一样的

显然,这里相当于有一个商为 \((q_1+q_2)\) ,余数为 \(r_1+r_2\) 的数模 \(m\) ,当然就等于直接对 \(r_1+r_2\) 模 \(m\) (不妨自己试一下,\(9 \bmod 2\) 和 \(1 \bmod 2\)一不一样)

所以我们有:

\[((q_1+q_2)m+r_1+r_2) \bmod m = (r_1+r_2) \bmod m \]

而 \(r_1,r_2\) 就是 \(a \bmod m\) ,\(b \bmod m\) ,带入得:

\[(r_1+r_2) \bmod m = ((a \bmod m)+(b \bmod m)) \bmod m \]

证毕

证明2:

仍然依据带余除法,我们设 \(a = q_1m + r_1,\) \(b = q_2m + r_2\),那么带入等式左边,我们有:

\[(a \times b)\bmod m = ((q_1m+r1) \times (q_2m + r_2)) \bmod m \]

展开:

\[= (q_1q_2m^2+(q_1r_2+q_2r_1)m+r_1r_2) \bmod m \]

这里括号内的前两项仍然是 \(m\) 的倍数,所以可以和1一样进行替换

\[= (r_1r_2) \bmod m \]

而 \(r_1\) 、\(r_2\) 分别是 \(a \bmod m\) ,\(b \bmod m\) ,带入得:

\[= ((a \bmod m) \times (b \bmod m)) \bmod m \]

证毕

同余

如果在计算过程中出现了负数,应该如何处理呢(也就是对负数取模,这里不能直接取,这样是负的)?

我们回归问题的本质:求出这个负数除以m的余数

也就是说,我们只要找到一个和这个负数除以m的余数一样的正数,就可以找到这个负数除以m的余数,而所谓的"和这个负数除以m的余数一样的正数",简称和这个负数同余(具有同样的余数)

当然,仅说同余是没有意义的,我们需要指定模数(除数),才是有意义的;

具体而言:假如有两个整数 \(x,y\) ,若 \((x-y) \bmod m = 0\) ,则称 \(x,y\) 在模 \(m\) 意义下同余(具有同样的余数)

为什么差是倍数就同余呢 ,仍然依据带余除法,我们设 \(x = q_1m + r_1,\) \(y = q_2m + r_2\),那么带入等式左边,我们有:

\[原式 = ((q_1-q_2)m+(r_1-r_2)) \bmod m \]

而因为这玩意为0,所以 \((q_1-q_2)m+(r_1-r_2)\) 必然是 \(m\) 的倍数,也就是能写成 \(n \times m\)的形式( \(n\) 是一个整数),显然,\(n = q_1-q_2\) ,所以 \(r_1 - r_2 = 0\),也就是说,\(r_1 = r_2\) ,即 \(x,y\) 同余;

现在给出定义:对于任意的两个数 \(x,y\) ,若有 \((x-y) \bmod m = 0\) ,那么我们称 \(x,y\) 在模 \(m\) 意义下同余,记为:

\[x \equiv y\pmod m \]

那么回到最初的问题:如何找到和这个负数同余的正数;

我们假设这个数是 \(-15\),根据同余的定义,我们有:\(-15 \equiv 5 \pmod{10}\) (\(-15-5 = -20 \bmod 10 = 0\) ,显然-20是10的-2倍)

那么怎样从 \(-15\) 推出 \(5\) 来呢?

我们使用 「模m加m」 的方法,即先模m得到一个负数,随后加上m,就得到了和m同余的正数:
\(-15 \bmod 10 = -5\),\(-5+10 = 5\),这样就得到了5,随后再对5模10即可(这里的负余数-5是大部分的编程语言的默认做法,但是不符合数学定义);

对于对一个不知正负的数字 \(x\) 取模,我们进行如下计算:
\(x \bmod m = (x \bmod m + m) \bmod m\)

最后

到这里这篇介绍模运算的文章就结束了(当然不包含对除法的取模,这个比较复杂,需要适当了解群论和乘法逆元),可能会有笔误,欢迎各位指正

相关推荐
欧阳小猜1 小时前
深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
人工智能·深度学习·算法
小欣加油1 小时前
leetcode 904 水果成篮
c++·算法·leetcode
有Li1 小时前
CXR-LT 2024:一场关于基于胸部X线的长尾、多标签和零样本疾病分类的MICCAI挑战赛|文献速递-深度学习人工智能医疗图像
论文阅读·人工智能·算法·医学生
君万2 小时前
【LeetCode每日一题】56. 合并区间
算法·leetcode·golang
墩墩同学2 小时前
【LeetCode题解】LeetCode 287. 寻找重复数
算法·leetcode·二分查找
小南家的青蛙2 小时前
LeetCode第55题 - 跳跃游戏
算法·leetcode·职场和发展
啊我不会诶2 小时前
CF每日4题(1500-1700)
c++·学习·算法
shuououo4 小时前
集成算法学习笔记
笔记·学习·算法
呼啸长风4 小时前
漫谈散列函数
算法
NAGNIP4 小时前
彻底搞懂 RoPE:位置编码的新范式
算法