关于模运算

前言

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

最后

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

发表评论

评论已关闭。

相关文章