Pollard's Rho 学习笔记
找出因子
给定正整数 \(n\),求出 \(n\) 的一个因子 \(k\)。
对于所有数据,\(1\leq n\leq10^{18}\)。
Solution
先用 Miller-Rabin 把 \(n\) 为素数的情况判了。
根据生日悖论,生成 \(\sqrt{\dfrac{\pi n}{2}}\) 个 \(1\sim n\) 的数就期望得到两个相等的数,下文将 \(\sqrt{\dfrac{\pi n}{2}}\) 看作 \(\sqrt{n}\)。
一个合数 \(n\) 肯定有一个 \(\le \sqrt{n}\) 的因子 \(d\),那么生成 \(\mathcal{O}(\sqrt[4]{n})\) 个数就期望得到两个数 \(x\equiv y\pmod d\)。
\(x\equiv y\pmod d\Rightarrow x-y\equiv0\pmod d\Rightarrow d\mid\gcd(|x-y|,n)\),所以 \(\gcd(|x-y|,n)\) 就是 \(n\) 的一个因子。考虑枚举 \(x,y\),可以做到 \(\mathcal{O}(\sqrt{n}\log n)\)。
但是 Pollard 定义了一个随机数生成器 \(f(x)=x^2+c\),并设置了一个数列 \(\{a_n\}\) 令 \(a_0=k\),\(a_{i+1}=f(a_i)\),其中 \(k,c\) 是随机的参数。
为什么要这样呢?因为这样的数列有一个性质:如果 \(a_{i}-a_{j}\equiv 0\pmod d\),则:
也就是说我们枚举的 \(a_{i},a_{j}\) 最好 \(j-i\) 是不同的。并且,\(\{a_n\}\) 是有环的。
我们可以使用 Floyd 判圈算法,定义 \(s=a_{k},t=a_{2k+1}\),若 \(s=t\) 则说明进入环中,直接返回重新选择 \(k,c\)。若某时刻 \(\gcd(|s-t|,n)\neq 1\) 则返回 \(\gcd(|s-t|,n)\) 作为一个因子。
时间复杂度
时间复杂度为 \(\mathcal{O}(n^{\frac{1}{4}}\log n)\),理由:
\(\gcd(|s-t|,n)\neq 1\) 意味着 \(s\equiv t\pmod d\)。设数列 \(b_{i}=a_{i}\mod d\),根据生日悖论,只要生成的序列足够随机,\(\{b_n\}\) 的环长期望为 \(\sqrt{d}\)。也就是说我们只需要期望 \(\mathcal{O}(\sqrt{d})\) 次就能找出一个因子。算上 gcd 的复杂度,\(\mathcal{O}(\sqrt{d}\log n)\leq\mathcal{O}(n^{\frac{1}{4}}\log n)\)。
Code
LL floyd(LL n) {
LL seed = rnd() % n, s, t;
auto f = [&](LL x) { return (mul(x, x, n) + seed) % n; };
s = t = rnd() % n, t = f(t);
while (s != t) {
LL d = __gcd(s - t + n, n);
if (d != 1) return d;
s = f(s), t = f(f(t));
}
return 1;
}
分解质因数
给定 \(n\),将其分解质因数。有 \(T\) 组数据。
$对于所有数据,\(1\leq n\leq 10^{18}\),\(1\leq T\leq350\)。
Solution
若 \(n\) 为质数则贡献答案,否则求出 \(n\) 的一个因子 \(d\),再递归求解 \(d\) 与 \(n/d\)。
时间复杂度 \(T(n)=n^{\frac{1}{4}}\log n+T(d)+T(n/d)\),根据主定理 \(T(n)=\mathcal{O}(n^{\frac{1}{4}}\log n)\)。
Code
void PollardRho(LL n, map<LL, LL>& res) {
LL d = 1;
if (n == 1) return;
if (MillerRabin(n)) { res[n] ++; return; }
while (d == 1) d = floyd(n);
PollardRho(d, res), PollardRho(n / d, res);
}

浙公网安备 33010602011771号