Miller-Rabin 素性检验

Miller-Rabin 素性检验

费马素性检验

费马小定理提出, 也就是对于所有小于 nn 的正整数 aa, 有 an11(modn)a^{n - 1} \equiv 1 \pmod n.

所以只要我们可以找到一个 a<na < n, 使得 an1≢1(modn)a^{n - 1} \not\equiv 1 \pmod n, 那么就可以确定 nn 不是一个素数.

对于合数 nn, 一定存在 aa 使得 an1≢1(modn)a^{n - 1} \not\equiv 1 \pmod n. 取 aa 使得 gcd(a,b)1\gcd(a, b) \neq 1, 会发现无论 aa 的多少次方, 都不会出现对 gcd(a,b)\gcd(a, b) 取模不为 00 的结果, 所以一定不会出现 11.

我们随机找一个正整数 a<na < n, 测试 an1a^{n - 1}nn 取模的结果是否为 11. 重复此过程一定的次数, 如果都是 11, 即可在一定的概率下得到 nn 是一个质数的结论. 否则就可以断定 nn 是合数. 这就是费马素性检验.

值得注意的是, 对于 gcd(a,n)=1\gcd(a, n) = 1aa, 没有定理证明了一定存在这样的 aa 使得 an11(modn)a^{n - 1} \equiv 1 \pmod n. 事实上, 可以找到这样的反例, 当 n=561n = 561 时, 对于所有 gcd(a,n)=1\gcd(a, n) = 1aa, 都有 an11(modn)a^{n - 1} \equiv 1 \pmod n. 这样的反例可以找到很多, 比如 10510^5 以内的反例就有: 561561, 11051105, 17291729, 24652465, 28212821, 66016601, 89118911, 1058510585, 1584115841, 2934129341, 4104141041, 4665746657, 5263352633, 6274562745, 6397363973, 7536175361.

这种数叫做卡迈克尔数, 在 OEIS 中有数列A002997介绍了这种数. 费马素性检验在遇到卡迈克尔数的时候的正确率非常差, 因此一般不用于实践.

模意义下 11 的平方根

对于模 nn 意义下 11 的平方根 xx, 满足 x21(modn)x^2 \equiv 1 \pmod n.

x21(modn)x210(modn)(x1)(x+1)0(modn)kn=(x1)(x+1)\begin{aligned} x^2 &\equiv 1 \pmod n\\ x^2 - 1 &\equiv 0 \pmod n\\ (x - 1)(x + 1) &\equiv 0 \pmod n\\ kn &= (x - 1)(x + 1)\\ \end{aligned}

如果 nn 是一个质数, 那么显然 xx 只有两种情况 11n1n - 1. 因为本来不含因子 nn 的两个正整数 aa, bb 相乘后仍然不含因子 nn, 所以模 nn 意义下 x1x - 1x+1x + 1 必有一个为 00.

但是如果 nn 是合数, xx 就可以是别的数了, 因此如果模 nn 意义下一个数 xx 的平方为 11, 而 xx 不是 111-1, 那么 nn 无疑是一个合数. Miller-Rabin 素性检验就是在费马素性检验的基础上多判了这种情况.

Miller-Rabin 素性检验

我们把 n1n - 1 表示成 2s2^s 和奇数 dd 的乘积, 重新审视费马小定理的式子:

an11(modn)a2sd1(modn)a2sd10(modn)(a2s1d1)(a2s1d+1)0(modn)(ad1)i=0s1(a2id+1)0(modn)\begin{aligned} a^{n - 1} &\equiv 1 \pmod n\\ a^{2^sd} &\equiv 1 \pmod n\\ a^{2^sd} - 1 &\equiv 0 \pmod n\\ (a^{2^{s - 1}d} - 1)(a^{2^{s - 1}d} + 1) &\equiv 0 \pmod n\\ (a^d - 1)\prod_{i = 0}^{s - 1}(a^{2^id} + 1) &\equiv 0 \pmod n\\ \end{aligned}

所以 ad1a^d - 1, a2id+1a^{2^id} + 1 在模 nn 意义下只要有一个是 00 即可认为 an11(modn)a^{n - 1} \equiv 1 \pmod n. 这样就不会放过费马素性检验所能检验的所有情况.

nn 如果是合数的话, 可能存在所有 ad1a^d - 1, a2id+1a^{2^id} + 1 都不是 00, 但是满足 an11(modn)a^{n - 1} \equiv 1 \pmod n, 这是因为这些非零项相乘时得到了 nn 的倍数, 所以得到最终结果为 00. 这种情况不会被费马素性检验判为合数, 但是 Miller-Rabin 却可以判为合数.

我们思考这样判断的理由.

如果遇到 a2i1da^{2^{i - 1}d} 不是 11 也不是 1-1, 但是 a2ida^{2^id} 却是 11, 根据前面对 11 的平方根的研究, 此时 nn 一定是个合数.

我们把 ad1a^d - 1, ad+1a^d + 1, a2d+1a^{2d} + 1,…, a2s1d+1a^{2^{s - 1}d} + 1 排成一个序列.

我们发现序列中最多只会出现一个 00, 有 00 则必定 an11(modn)a^{n - 1} \equiv 1 \pmod n. 讨论第一次出现 00 是什么时候. 如果第一个 00a2id+1a^{2^id} + 1, 则 a2idn1(modn)a^{2^id} \equiv n - 1 \pmod n. 那么将它平方后一定得到 11, 因此之后的项都是 1+1=21 + 1 = 2. 如果第一个 00ad1a^d - 1, 说明 ad=1a^d = 1, 因为 11 的正整数次方都是 11, 那么从第二项开始, 就一定都是 1+1=21 + 1 = 2.

接下来就是序列中没有 00 的情况.

讨论 an1a^{n - 1} 是否为 11. 如果 an1a^{n - 1}11, 说明是在没有出现 1-1 的情况下就平方出了 11, 根据前面推得的结论, 不是 111-1 的数字平方得到 11, 则 nn 是合数, 所以这时判为合数是正确的. 如果 an1a^{n - 1} 不是 11, 那么根据费马素性检验, nn 是一个合数.

因此我们只要判断所有 ad1a^d - 1, a2id+1a^{2^id} + 1 是否全部非 00, 如果不存在 00 就认为 nn 是个合数即可. 算法实现时先求 ada^d, 可以快速得到前两项, 然后不断将 ada^d 平方即可得到所有的项加 1-1 的结果.

算法效率和正确性

对于每个合数 nn, 可以判出 nnaa 是很多的, 所以期望只要很少次测试就可以把合数判断出来. 接下来是对英文维基百科页面的简化与复述. (这么重要的内容中文页面为什么不写?!)

根据广义黎曼猜想(我也不知道讲的是什么), 不能判出 nnaa 最多有 O((lnn)2)O((\ln n)^2) 个, 而这个大 OO 记号的常数被美国计算机科学家 Eric Bach 减少到了 22, 也就是说我们判断 2((lnn)2)2((\ln n)^2)aa 就可以判断出 nn.

但是黎曼猜想的正确性现在也没有被证明, 更不用说广义黎曼猜想了, 所以为了能在有限范围内正确地快速判断质数, 我们有一些已经被验证的结论:

现在已经知道对于 n<4759123141n < 4759123141 的情况, 我们只需要判断 a=2,7,61a = {2, 7, 61} 即可. 对于 n<3317044064679887385961981n < 3317044064679887385961981, 只要判断 a=2,3,5,7,11,13,17,19,23,29,31,37,41a = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41}.

参考文献