参考
题解 P4718/论 Miller-Rabin 算法的确定性化 - 洛谷专栏
Miller Rabin 算法
该算法能够 \(O(\log^3p)\) 判定 \(p\) 是否是质数。
费马素性检测
定理:若 \(p\) 为素数,则 \(\forall a,1\leq a<p\),有 \(a^{p-1}\equiv 1\ (\operatorname{mod}\ p)\)。
这个就是费马小定理。
二次探测定理
定理:若 \(p\) 为素数,则关于 \(x\) 的方程 \(x^2\equiv 1\ (\operatorname{mod}\ p)\) 的解集为 \(x\equiv \pm 1\ (\operatorname{mod}\ p)\)。
证明:因为 \(x^2\equiv 1\ (\operatorname{mod}\ p)\),所以 \(p\mid (x^2-1)\),因为 \(x^2-1=(x+1)(x-1)\),所以 \(p\mid x+1\) 或 \(p\mid x-1\),这就能说明正确性了。
大致思路
于是,我们就有一个做法了。我们要不断地随机一些底数 \(a\) 来验证 \(p\) 是否是素数。
对于一个 \(a\),我们这么验证。首先,要满足 \(a^{p-1}\equiv 1\ (\operatorname{mod}\ p)\)。于是我们得到了 \(a^{t}\equiv 1\ (\operatorname{mod}\ p)\)(这里 \(t=p-1\))。
如果 \(t\) 是偶数,那么可以得到关于 \(a^{\frac{t}{2}}\) 的方程 \((a^{\frac{t}{2}})^2\equiv 1\ (\operatorname{mod}\ p)\),于是一定要满足 \(a^{\frac{t}{2}}\equiv \pm 1\ (\operatorname{mod}\ p)\)。如果 \(a^{\frac{t}{2}}\equiv -1\ (\operatorname{mod}\ p)\),那么就结束对于这个 \(a\) 的验证。否则,就有 \(a^{\frac{t}{2}}\equiv 1\ (\operatorname{mod}\ p)\),令 \(\displaystyle t\gets \frac{t}{2}\),于是又有 \(a^{t}\equiv 1\ (\operatorname{mod}\ p)\) 了,继续验证。
复杂度分析
如果进行 \(T\) 次随机选取底数 \(a\),则复杂度容易做到 \(O(T\log^2 p)\)(使用快速幂),如果实现精细,可以做到 \(O(T\log p)\)。
这里有一个结论。如果承认广义黎曼猜想,则底数 \(a\) 只需要取遍前 \(O(\log^2 p)\) 个自然数即可。所以复杂度可以做到 \(O(\log^3p)\)。
如果不随机选取 \(a\) 的值,则 \(a\) 被推荐取遍下表中的值。
\(p\) 不超过的值 | 推荐取值 | 记忆 |
---|---|---|
\(2^{31}\) | \(\{2,7,61\}\) | 不推荐记忆 |
\(2^{64}\) | \(\{2,325,9375,28178,450775,9780504,1795265022\}\) | 不推荐记忆 |
\(2^{78}\) | \(\{2,3,5,7,11,13,17,19,23,29,31,37\}\) | 前 \(12\) 个素数 |
Pollard Rho 算法
该算法能期望 \(O(N^{\frac{1}{4}})\) 获取合数 \(N\) 的一个因子。
生日悖论
问题:给定正整数 \(V\),初始集合 \(S\) 为空,执行下过程:
- 在集合 \([V]\) 中等概率随机选取一个数 \(x\),若 \(x\not\in S\),则将 \(x\) 加入集合 \(S\),并重新执行本过程;否则停止执行。
问集合 \(|S|\) 的期望。
结论:\(|S|\) 的期望为
不会证捏。
大致思路
下文中,我们要分解的数为 \(N\)。
Pollard Rho 的大致思路为,先构造一个随机函数 \(f\),然后不断生成随机数。对于生成的随机数 \(a,b\),若 \(d=\gcd(|a-b|,N)\) 在 \((1,N)\) 之中,则 \(d\) 为 \(N\) 的一个因数。
而 \(d\in (1,N)\) 仅当存在一个质数 \(p\mid N\) 满足
这里 \(a\) 和 \(b\) 在模 \(p\) 意义下相同,这使得我们可以猜想,只需要期望生成 \(O(\sqrt p)\)(因为 \(O(p)=O(\sqrt N)\),故为 \(O(N^{\frac{1}{4}})\))个随机数就能达到目的。
Pollard Rho 的随机函数
Pollard Rho 使用的随机函数为(其中 \(c\) 为某常数)
性质:对于正整数 \(p\mid N\),若 \(x\equiv y\ (\operatorname{mod}\ p)\),则 \(f(x)\equiv f(y)\ (\operatorname{mod}\ p)\)。
证明:由于 \(p\mid N\),所以在模 \(p\) 意义下,\(f(x)=(x^2+c)\bmod p\)。由于 \(x\equiv y\ (\operatorname{mod}\ p)\),所以 \(0\equiv x-y\equiv (x-y)(x+y)+c-c\equiv x^2+c-(y+c)\ (\operatorname{mod}\ p)\),所以 \(x^2+c\equiv y^2+c\ (\operatorname{mod}\ p)\)。这样就说明了性质的正确性。
这一性质使得,当我们生成了 \(n\) 个随机数时,可能只需要 \(O(n)\) 次计算就能检验是否应该停止生成随机数了。
Floyed 判环
大多数时候(或许时所有的时候),\(f\) 生成的随机数会产生混循环,所以需要判断是否进入了混循环,并考虑跳出。
可以使用 Floted 算法判环。在一个 \(\rho\) 形图中,可以使用两个指针 \(x,y\),每次让 \(x\) 前进一步,\(y\) 前进两步,如果 \(x\) 和 \(y\) 重合了,就说明有环。这样复杂度是 \(O(\)环长\()\) 的。
并且,求 \(\gcd\) 时也可以顺便求 \(x\) 和 \(y\) 之间的。
分组求 gcd
直接做复杂度是 \(O(N^{\frac{1}{4}}\log N)\) 的(要求 \(O(N^{\frac{1}{4}})\) 次 \(\gcd\)),能否去掉 \(\log N\) 呢?
可以将 \(O(N^{\frac{1}{4}})\) 个数分为 \(O(\log N)\) 组,每组求一次 \(\gcd\),复杂度就是 \(O(N^{\frac{1}{4}})\) 的啦。
伪代码
- \(\text{ctz}(x)\) 表示正整数 \(x\) 在二进制下,最低位连续 \(0\) 的个数。
- \(M\in \mathbb{N}^{+}\)
- function \(\text{mul}(x,y)\)
- return \(xy\bmod M\)
- function \(\text{isprime}(p)\)
- 静态数组 \(\text{prime}=(2,3,5,7,11,13,17,19,23,29,31,37)\)
- if \(p\leq 40\) then
- return \([p\in \text{prime}]\)
- \(M\gets p\)
- let \(t=p - 1, u = \text{ctz}(t)\)
- \(\displaystyle t\gets t\times \frac{1}{2^u}\)
- for \(a\in \text{prime}\) do
- let \(x = a ^ t\)
- if \(x = 1\) or \(x = p - 1\) then
- continue
- let \(\text{ok} = \textbf{false}\)
- for \(i \in (1,2,\dots,u-1)\) do
- \(x \gets \text{mul}(x, x)\)
- if \(x = p - 1\) then
- \(\text{ok} \gets \textbf{true}\)
- break
- if \(\text{ok} = \textbf{false}\) then
- return \(\textbf{false}\)
- return \(\textbf{true}\)
- \(c = 1\)
- function \(f(x)\)
- return \((\text{mul}(x,x)+c)\bmod M\)
- \(B = 64\)
- function \(\text{rho}(N)\)
- if \(N \bmod 2 = 0\) then
- return \(2\)
- \(M\gets N\)
- let \(x = 0, y = 0, z = 0, \Pi = 1\)
- for \(\displaystyle i\in (\lfloor\frac{B}{2}\rfloor,\lfloor\frac{B}{2}\rfloor+1,\lfloor\frac{B}{2}\rfloor+2,\dots)\) do
- if \(x = y\) then
- \(z\gets z + 1\)
- \(x \gets z\)
- \(y \gets f(x)\)
- let \(t = \text{mul}(\Pi, |x - y|)\)
- if \(t\neq 0\) then
- \(\Pi\gets t\)
- if \(i\bmod B = 0\) then
- let \(d = \gcd(\Pi,N)\)
- if \(1 < d\) then
- return \(d\)
- \(x\gets f(x)\)
- \(y\gets f(f(x))\)
- if \(x = y\) then
- if \(N \bmod 2 = 0\) then