关于模运算

前言

写这篇文章的时候,本蒟蒻正在挑战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\)

最后

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

相关推荐
DeepModel3 分钟前
机器学习数据预处理:特征构造
人工智能·学习·算法·机器学习
棋子入局7 分钟前
C语言实现消消乐游戏(6)
c语言·算法·游戏
Mem0rin14 分钟前
[Java]排序
java·算法·排序算法
qeen8734 分钟前
【算法笔记】差分与经典例题解析
c语言·c++·笔记·学习·算法·差分
kronos.荒39 分钟前
动态规划——整数拆分(python)
python·算法·动态规划
cici158741 小时前
基于Koopman模型预测控制的非线性流控制数据驱动框架
算法
6Hzlia1 小时前
【Hot 100 刷题计划】 LeetCode 416. 分割等和子集 | C++ 0-1背包 1D空间极致优化
c++·算法·leetcode
穿条秋裤到处跑1 小时前
每日一道leetcode(2026.04.21):执行交换操作后的最小汉明距离
java·算法·leetcode
Tina学编程1 小时前
算法训练Day10 | LeetCode 169 多数元素
算法·leetcode
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2026.04.22 题目:2452. 距离字典两次编辑以内的单词
笔记·算法·leetcode