转自:http://jaskell.blogbus.com/logs/3249971.html

一、同余

    我们来了解一下什么是“同余”。简单来说就是,如果两个数都除以某个数能够有相同的余数,那么我们就说这两个数“同余”。不过这次我们用严谨的数学概念来表述:

    两个整数 ab,若它们除以整数 m 所得的余数相等,则称 ab 对于模 m 同余

    记作 a

    读作 a 同余于 b m ,或读作 a b 关于模 m 同余。

    比如 26

    我们再来了解一下相关的性质:

  1. 如果 a ,那么 m | (ab) ,这里 m | (ab) 表示 (ab) 能被 m 整除
  2. 如果 a b , 那么a
  3. 如果 a c , 那么a+c a-c ac a/c
  4. 如果 a , 那么 a^n  

    有了这些性质,判断两个数是否同余就可以用更简单的方法了。根据性质一,原来我们需要判断 (a mod m) == (b mod m) 是否为真,现在就可以直接判断 (a - b) mod m == 0 是否为真了。这样就把其中一次求余运算变为减法运算了。一般来说减法要比除法更容易在计算机上实现,运算速度也更快。


二、求余 (a * b * c * d) mod m = ?

    由于计算机表示一个整数通常用 32bit 。而大量连乘运算则可能会导致整数溢出,这时我们就要利用求余一些性质来进行处理了。把以上式子转换为:

    已知: (a * b) mod m == ((a mod m) * b) mod m

    所以: (a * b * c * d) mod m = ((((((a mod m) * b) mod m) * c) mod m) * d) mod m

    这样就把连乘运算分解了,每次可以先进行求余运算然后再进行乘法运算。