写在前面
模运算在计算机算法中经常都回出现, 如果不知道原理的话, 可能看他人代码也会出现看不懂的情况, 这篇帖子存在的主要目的是作为未来写blog的时候有一个方便理解的引论. 笔记本身是写在GoodNote上面的, 手写部分 可能也会出现在帖子中
关于持续更新
如果我未来在算法题目中遇到了新的不懂的模运算相关知识, 我会更新这篇文章
模运算
基础定义
定义: 对于任意 x,y, 存在 x mod y = x - y*[x/y] (向下取整) 即:
则称 x mod y 为 x 对 y 取模
例如: x = 5, y = 2, 5 mod 2 = 5 - 2[5/2] = 5 - 4 = 1
其实就是我们小学学的 余数
为了完整, 避免0做除数, 我们定义: 任意数与0的模都是其本身
例如: x = 5, y = 0; 5 mod 0 = 5
模运算规则
-
a % p % p = a % p即多次取模, 模不变
证明:
设: a % p = x, 则 x < p
a % p % p = x % p = x -
(a + b) % p = (a % p + b % p) % p
证明:
设 a % p = x, b % p = y;
则: a = k1p + x, b = k2p + y; (k1为 a/p 向下取整, k2 同理)
则: a + b = (k1 + k2)*p + x + y
则: (a + b)%p = (x + y)%p (因为 (k1 + k2)*p 部分一定会被p整除, 因此结果不含 k1 k2, 而我们不知道 x + y 是否大于 p, 因此需要对 p 取模, 目的是保证 结果 要 < p)
将 x 与 y 用 我们之前的设 代替:
(a + b)%p = (x + y)%p = (a%p + b%p)%p 为所求 -
[(a%p) * (b%p)] % p = (a%p * b%p) % p
证明:
设 a % p = x, b % p = y;
左边: (x * y) % p
右边: (x * b%p) % p
因为 b = y + p * [b/p] (向下取整符号)
右边
(x * (y + p * [b/p])%p) % p
= [ x * y + x * p * [b/p]] % p % p
= [ x * y + x * p * [b/p]] % p
= ((x * y)%p + (x * p * [b/p]) % p) % p (由 2 可得)
= (x * y + 0) % p (x * p * [b/p] 一定是p的倍数, 因此取模为0)
= 左边 -
(a * b) % p = (a % p * b % p) % p
证明:
设 a % p = x, b % p = y;
则: a = k1 * p + x, b = k2 * p + y;
a * b
= (k1 * p + x) * (k2 * p + y)
= k1 * k2 * p² + k1 * y * p + k2 * x * p + x * y
因此: (a * b) % p = (0 + 0 + (x * y) % p) % p (由2可得)
即 (a * b) % p = (x * y) % p = (a % p * b % p) % p (由3可得) -
a % p * b % p = a * b % p
证明:
设 a % p = x, b % p = y;
则: a = k1 * p + x, b = k2 * p + y;
左边 = x * ( y + p * k2) % p
= (x * y + p * x * k2) % p
= ((x * y) % p + 0) % p
= (x * y) % p右边 = (k1 * p + x) * (k2 * p + y) % p
= (k1 * k2 * p² + k1 * y * p + k2 * x * p + x * y) % p
= (x * y) % p = 左边