OSDN Git Service

update pollard-rho
authorscheng <scheng52123@gmail.com>
Fri, 6 Nov 2020 14:34:50 +0000 (22:34 +0800)
committerscheng <scheng52123@gmail.com>
Fri, 6 Nov 2020 14:34:50 +0000 (22:34 +0800)
docs/math/images/Pollard-rho1.png [new file with mode: 0644]
docs/math/pollard-rho.md

diff --git a/docs/math/images/Pollard-rho1.png b/docs/math/images/Pollard-rho1.png
new file mode 100644 (file)
index 0000000..4b709d7
Binary files /dev/null and b/docs/math/images/Pollard-rho1.png differ
index c2d2d02..410cb78 100644 (file)
@@ -12,7 +12,7 @@ Pollard-Rho 算法是一种用于快速分解质因数的算法。
 
 不考虑出生年份,问:一个房间中至少多少人,才能使其中两个人生日相同的概率达到 $50\%$ ?
 
-解:假设一年有 $n$ 天,屋子中有 $k$ 人,用整数 $1, 2,\dots, k$ 对这些人进行编号。假定每个人的生日均匀分布于 $n$ 天之中,且两个人的生日相互独立。
+解:假设一年有 $n$ 天,房间中有 $k$ 人,用整数 $1, 2,\dots, k$ 对这些人进行编号。假定每个人的生日均匀分布于 $n$ 天之中,且两个人的生日相互独立。
 
 设 k 个人生日互不相同为事件 $A$ , 则事件 $A$ 的概率为
 
@@ -29,21 +29,17 @@ P(A) \le e^{-\frac{1}{n}}\times e^{-\frac{2}{n}}\times \dots \times e^{-\frac{k-
 e^{-\frac{k(k-1)}{2n}}\le\frac{1}{2}
 $$
 
+然而我们可以得到一个不等式方程, $e^{-\frac{k(k-1)}{2n}}\le 1-p$ ,其中 $p$ 是一个概率。
+
 将 $n=365$ 代入,解得 $k=23$ 。所以一个房间中至少 23 人,使其中两个人生日相同的概率达到 $50\%$ , 但这个数学事实十分反直觉,故称之为一个悖论。
 
-然而我们可以得到一个不等式方程, $e^{-\frac{k(k-1)}{2n}}\le 1-p$ ,其中 $p$ 是一个概率。那么当 $k=57$ , $n=365$ 时,可以求得 $p\approx 0.99$ 
+当 $k>60$ , $n=365$ 时,出现两个人同一天生日的概率将大于$99\%$ 。那么在一年有$n$天的情况下,当房间中有$\sqrt{n}$个人时,至少有两个人的生日相同
 
 考虑一个问题,设置一个数据 $n$ ,在 $[1,1000]$ 里随机选取 $i$ 个数( $i=1$ 时就是它自己),使它们之间有两个数的差值为 $k$ 。当 $i=1$ 时成功的概率是 $\frac{1}{1000}$ ,当 $i=2$ 时成功的概率是 $\frac{1}{500}$ (考虑绝对值, $k_2$ 可以取 $k_1-k$ 或 $k_1+k$ ),随着 $i$ 的增大,这个概率也会增大最后趋向于 1。
 
-## 优化随机算法
-
-最大公约数一定是某个数的约数,即 $\forall k \in\mathbb{N}_{+},\gcd(k,n)|n$ ,只要选适当的 $k$ 使得 $1<\gcd(k,n)< n$ ,就可以求得一个约数 $\gcd(k,n)$ 。满足这样条件的 $k$ 不少, $k$ 有若干个质因子,每个质因子及其倍数都是可行的。
-
-根据生日悖论,取多组数据作差能够优化取数的精确性。那么不妨取一组数 $x_1,x_2,\dots,x_n$ 若有 $1<\gcd(|x_i-x_j|,n) < n$ , 则称 $\gcd(|x_i-x_j|,N)$ 是 $N$ 的一个因子(更严谨一些,应该是非平凡因子,即满足 $1< d < n,d|n$ 的那些数)。
-
 ### 构造伪随机函数
 
\9e\84é\80 ä¸\80个伪é\9a\8fæ\9cºæ\95°åº\8få\88\97ï¼\8cå\8f\96ç\9b¸é\82»ç\9a\84两项æ\9d¥æ±\82 $\gcd(|x_i-x_j|,N)$ ã\80\82é\80\9aè¿\87 $f(x)=(x^2+c)\bmod n$ æ\9d¥ç\94\9fæ\88\90é\9a\8fæ\9cºæ\95°,其中 $c=rand()$ ,是一个随机的常数。
\88\91们é\80\9aè¿\87 $f(x)=(x^2+c)\bmod n$ æ\9d¥ç\94\9fæ\88\90ä¸\80个é\9a\8fæ\9cºæ\95°åº\8få\88\97$\{x_i\}$,其中 $c=rand()$ ,是一个随机的常数。
 
 随机取一个 $x_1$ ,令 $x_2=f(x_1),x_3=f(x_2),\dots,x_i=f(x_{i-1})$ ,在一定范围内可以认为这个数列是“随机”的。
 
@@ -55,6 +51,34 @@ $$
 
 可以发现数据在 3 以后都在 11,23,31 之间循环,这也是 $f(x)$ 被称为伪随机函数的原因。
 
+如果将这些数如下图一样排列起来,会发现这个图像酷似一个$\rho$,算法也因此得名rho。
+
+![Pollard-rho1](./images/Pollard-rho1.png)
+
+## 优化随机算法
+
+最大公约数一定是某个数的约数,即 $\forall k \in\mathbb{N}_{+},\gcd(k,n)|n$ ,只要选适当的 $k$ 使得 $1<\gcd(k,n)< n$ ,就可以求得一个约数 $\gcd(k,n)$ 。满足这样条件的 $k$ 不少, $k$ 有若干个质因子,每个质因子及其倍数都是可行的。
+
+将生日悖论应用到随机算法中,伪随机数序列中不同值的数量约为$O(\sqrt{n})$个。设$m$为$n$的最小非平凡因子,显然有$m\leq \sqrt{n}$。记$y_i = x_i \pmod m$,推导可得:
+
+$$
+\begin{aligned}
+y_{i+1}&=x_{i+1} \bmod m \\
+& = (x_{i}^2+c \bmod n) \bmod m \\
+& = (x_i ^ 2 + c) \bmod m \\
+& = ((x_i \bmod m) ^ 2 + c) \bmod m \\
+& = y_i ^ 2 + c \pmod m
+\end{aligned}
+$$
+
+于是就得到了一个新序列$\{y_i\}$(当然也可以写作$\{x_i \bmod m\}$),并且根据生日悖论可以得知序列中不同值的个数约为$O(\sqrt{m})\leq O(n^{\frac{1}{4}})$。
+
+假设存在两个位置$i,j$,使得$x_i\neq x_j\wedge y_i=y_j$,这意味着$n \nmid |x_i−x_j| \wedge m \mid |x_i−x_j|$,因此我们可以通过 $\gcd(n, |x_i-x_j|)$获得$n$的一个非平凡因子。
+
+### 时间复杂度分析
+
+我们期望枚举 $O(\sqrt{m})$个$i$来分解出 $n$ 的一个非平凡因子 $\gcd(|x_i−x_j|,n)$ ,因此。 Pollard-rho 算法能够在 $O(\sqrt{m})$的期望时间复杂度内分解出 $n$ 的一个非平凡因子,通过上面的分析可知$O(\sqrt{m})\leq O(n^{\frac{1}{4}})$,那么Pollard-rho 算法的总时间复杂度为$O(n^{\frac{1}{4}})$。下面介绍两种实现算法,两种算法都可以在$O(\sqrt{m}$的时间复杂度内完成。
+
 ### Floyd 判环
 
 假设两个人在赛跑,A 的速度快,B 的速度慢,经过一定时间后,A 一定会和 B 相遇,且相遇时 A 跑过的总距离减去 B 跑过的总距离一定是圈长的 n 倍。
@@ -83,7 +107,7 @@ $$
 
 使用 $\gcd$ 求解的时间复杂度为 $O(\log N)$ ,频繁地调用会使算法运行地很慢,可以通过乘法累积来减少求 $\gcd$ 的次数。如果 $1< \gcd(a,b)$ ,则有 $1< \gcd(ac,b)$ , $c\in \mathbb{N}_{+}$ ,并且有 $1< \gcd(ac \bmod b,b)=\gcd(a,b)$ 。
 
-我们每过一段时间将这些差值进行 $\gcd$ 运算,设 $s=\prod|x_0-x_j|\bmod n$ ,如果某一时刻得到 $s=0$ 那么表示分解失败,退出并返回 $n$ 本身。每隔 $2^k$ 个数,计算是否满足 $1< \gcd(s, n) < n$ 
+我们每过一段时间将这些差值进行 $\gcd$ 运算,设 $s=\prod|x_0-x_j|\bmod n$ ,如果某一时刻得到 $s=0$ 那么表示分解失败,退出并返回 $n$ 本身。每隔 $2^k-1$ 个数,计算是否满足 $1< \gcd(s, n) < n$ 。此处取$k=7$,可以根据实际情况进行调节
 
 ??? note "参考实现"
     ```c++