为什么每步取模
long long 上限约 9.2e18,看着很大,其实闷头累乘 1e9 才乘第三次就溢出成乱码,后面全错。而每步都 % MOD 的那条线,值永远被压在 0 到 1e9+6 之间,稳稳的。依据是取模的性质:加法、乘法都能逐步取模,先取再算和最后一起取,结果一样。课件用 2×3×5×7 走了一遍 res = res * nums[i] % MOD,从 res = 1 一步步乘到 210。
乘法与减法的两条铁律
① 乘法:a、b 都是 int 时直接 a * b % MOD 是错的——乘积先在 32 位里溢出,再取模也救不回来,必须写 (long long)a * b % MOD 让乘法在 64 位里做。② 减法:C 里负数取模结果可能为负(C99 向零取整,-3 % 7 得 -3),要写 ((a - b) % MOD + MOD) % MOD 把结果掰回 0 到 MOD-1,课件里 (3-10) 的例子掰回后是 1000000000。
除法不能直接除
取模世界里没有 (a / b) % MOD 这种写法。要用逆元把除法换成乘法:MOD 是质数时,由费马小定理 inv(b) = b^(MOD-2) % MOD,再算 a * inv(b) % MOD。求逆元用快速幂约 30 次乘法取模,O(log MOD);普通累加累乘用不上,先知道有这回事即可。