**离散对数的波拉德ρ算法**是约翰·波拉德（英语：）1978年所发明解决离散对数问题的算法。

算法的目标是求 \gamma  使得 {\displaystyle \alpha ^{\gamma }=\beta }，其中 \beta  属于一个由 \alpha  生成的 循环群 G。该算法寻找 a, b, A, B 使得 {\displaystyle \alpha ^{a}\beta ^{b}=\alpha ^{A}\beta ^{B}}。若他们基于的群是一个 n 阶的循环群，则 \gamma  是方程 {\displaystyle (B-b)\gamma =(a-A){\pmod {n}}} 的其中一个解。

为求得 a, b, A, B， 该算法使用 Floyd判圈算法 在数列 {\displaystyle x\_{i}=\alpha ^{a\_{i}}\beta ^{b\_{i}}} 中寻找一个环。 假设映射 {\displaystyle f:x\_{i}\mapsto x\_{i+1}} 是近似于随机的，则有可能在约 {\displaystyle {\sqrt {\frac {\pi n}{2}}}} 步后发现一个环。可使用一下规则来生成一个此类映射：将 G 分割为三个不相交的子集 S\_{0}，S\_{1}
，S\_{2} ，且其所含元素数量大致相等，如果 {\displaystyle x\_{i}\in S\_{0}} 则将 a 和 b 加倍； 如果 {\displaystyle x\_{i}\in S\_{1}} 则将 a 自增； 如果 {\displaystyle x\_{i}\in S\_{2}} 则将 b 自增。

算法
--

使 G 是一个 p 阶的 循环群, 且有 {\displaystyle \alpha ,\beta \in G}, 以及一个分割 {\displaystyle G=S\_{0}\cup S\_{1}\cup S\_{2}}, 定义映射 {\displaystyle f:G\to G}

{\displaystyle f(x)={\begin{cases}\beta x&x\in S\_{0}\\x^{2}&x\in S\_{1}\\\alpha x&x\in S\_{2}\end{cases}}}
并据以下方式定义映射 {\displaystyle g:G\times \mathbb {Z} \to \mathbb {Z} } 和 {\displaystyle h:G\times \mathbb {Z} \to \mathbb {Z} }

{\displaystyle {\begin{aligned}g(x,n)&={\begin{cases}n&x\in S\_{0}\\2n{\pmod {p}}&x\in S\_{1}\\n+1{\pmod {p}}&x\in S\_{2}\end{cases}}\\h(x,n)&={\begin{cases}n+1{\pmod {p}}&x\in S\_{0}\\2n{\pmod {p}}&x\in S\_{1}\\n&x\in S\_{2}\end{cases}}\end{aligned}}}

```
 **输入** *a*: a 是 *G* 的生成元, *b*: *G* 的一个元素
 **输出** 整数 *x* 使得 *ax* = *b*, 或者失败

 初始化 *a*0 ← 0, *b*0 ← 0, *x*0 ← 1 ∈ *G*, 

 *i* ← 1
 **loop**
     *xi* ← *f*(*x**i*-1), 
     *ai* ← *g*(*x**i*-1, *a**i*-1), 
     *bi* ← *h*(*x**i*-1, *b**i*-1)

     *x*2*i* ← *f*(*f*(*x*2*i*-2)), 
     *a*2*i* ← *g*(*f*(*x*2*i*-2), *g*(*x*2*i*-2, *a*2*i*-2)), 
     *b*2*i* ← *h*(*f*(*x*2*i*-2), *h*(*x*2*i*-2, *b*2*i*-2))

     **if** *xi* = *x*2*i* **then**
         *r* ← *bi* - *b*2*i*
         **if** r = 0 **return failure**
         *x* ← *r*−1(*a*2*i* - *ai*) mod *p*
         **return** *x*
     **else** # *xi* ≠ *x*2*i*
         *i* ← *i*+1, 
         **break loop**
     **end if**
  **end loop**
```

举例
--

例如一个由 2 模 {\displaystyle N=1019} 生成的群（群的阶是{\displaystyle n=1018}，2是生成元，生成群的元素模1019同余)。这个算法可由以下 C++ 程序实现。

```
 #include <stdio.h>
 
 const int n = 1018, N = n + 1; /\* N = 1019 -- 素数 \*/
 const int alpha = 2; /\* 生成元 \*/
 const int beta = 5; /\* 2^{10} = 1024 = 5 (N) \*/
 
 void new\_xab( int& x, int& a, int& b ) {
 switch( x%3 ) {
 case 0: x = x\*x % N; a = a\*2 % n; b = b\*2 % n; break;
 case 1: x = x\*alpha % N; a = (a+1) % n; break;
 case 2: x = x\*beta % N; b = (b+1) % n; break;
 }
 }
 
 int main(void) {
 int x=1, a=0, b=0;
 int X=x, A=a, B=b;
 for(int i = 1; i < n; ++i ) {
 new\_xab( x, a, b );
 new\_xab( X, A, B );
 new\_xab( X, A, B );
 printf( "%3d %4d %3d %3d %4d %3d %3d\n", i, x, a, b, X, A, B );
 if( x == X ) break;
 }
 return 0;
 }

```

结果如下 (已截断):

```
 i     x   a   b     X   A   B
------------------------------
 1     2   1   0    10   1   1
 2    10   1   1   100   2   2
 3    20   2   1  1000   3   3
 4   100   2   2   425   8   6
 5   200   3   2   436  16  14
 6  1000   3   3   284  17  15
 7   981   4   3   986  17  17
 8   425   8   6   194  17  19
..............................
48   224 680 376    86 299 412
49   101 680 377   860 300 413
50   505 680 378   101 300 415
51  1010 681 378  1010 301 416
```

可见 {\displaystyle 2^{681}5^{378}=1010=2^{301}5^{416}{\pmod {1019}}} 以及 {\displaystyle (416-378)\gamma =681-301{\pmod {1018}}}。
正如预期，其中 {\displaystyle \gamma \_{1}=10} 是一个解。由于 {\displaystyle n=1018} 不是素数，因此存在另一个解 {\displaystyle \gamma \_{2}=519}，使得 {\displaystyle 2^{519}=1014=-5{\pmod {1019}}} 成立。

复杂度
---

时间复杂度近似于 {\displaystyle {\mathcal {O}}({\sqrt {n}})}。如果配合使用 Pohlig-Hellman 算法（英语：），则整体时间复杂度近似于 {\displaystyle {\mathcal {O}}({\sqrt {p}})}，其中 p 是 n 的最大质因数。

参考文献
----

* Pollard, J. M.. Mathematics of Computation. 1978, **32** (143): 918–924. doi:10.2307/2006496.
* Menezes, Alfred J.; van Oorschot, Paul C.; Vanstone, Scott A.  (PDF).. 2001  [2018-04-16]. （原始内容 (PDF)存档于2012-02-08）.

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
数论算法 |
| --- |
|  |
| 素数测试 | 
* AKS
* APR（英语：）
* Baillie–PSW（英语：）
* 椭圆曲线（英语：）
* Pocklington（英语：）
* 费马
* 卢卡斯（英语：）
* *卢卡斯-莱默*
* *Lucas–Lehmer–Riesel（英语：）*
* *普罗斯*
* *Pépin（英语：）*
* 二次Frobenius（英语：）
* Solovay–Strassen（英语：）
* 米勒-拉宾

 |
|  |
| 質數生成（英语：） | 
* 阿特金筛法（英语：）
* 埃拉托斯特尼筛法
* Pritchard筛法（英语：）
* Sundaram筛法（英语：）
* 輪式因數分解法（英语：）

 |
|  |
| 整数分解 | 
* 連分數分解 (CFRAC)（英语：）
* Dixon's（英语：）
* Lenstra橢圓曲線 (ECM)（英语：）
* 欧拉因式分解法（英语：）
* 波拉德ρ算法（英语：）
* *p* − 1（英语：）
* *p* + 1（英语：）
* 二次篩選法
* 普通数域筛选法
* *特殊數域篩選法 (SNFS)（英语：）*
* 有理筛选法
* 费马因式分解法（英语：）
* Shanks二次形式（英语：）
* 试除法
* 秀爾演算法

 |
|  |
| 乘法算法 | 
* 古埃及乘算（英语：）
* 長乘法
* 卡拉楚巴算法
* 图姆-库克算法
* 頌哈吉-施特拉森演算法
* 富尔算法（英语：）

 |
|  |
| 歐幾里德除法除法算法 | 
* 二進制（英语：）
* 倍塊法（英语：）
* Fourier（英语：）
* Goldschmidt（英语：）
* Newton-Raphson（英语：）
* 長除法
* 短除法
* SRT

 |
|  |
| 离散对数 | 
* 大步小步算法
* 波拉德ρ算法
* Pollard kangaroo（英语：）
* Pohlig–Hellman（英语：）
* Index calculus（英语：）
* Function field sieve（英语：）

 |
|  |
| 最大公因數 | 
* 二进制最大公因数算法（英语：）
* 輾轉相除法
* 扩展欧几里得算法
* Lehmer's（英语：）

 |
|  |
| 二次剩余 | 
* Cipolla（英语：）
* Pocklington's（英语：）
* Tonelli–Shanks（英语：）
* Berlekamp（英语：）
* Kunerth（英语：）

 |
|  |
| 其他算法 | 
* Chakravala（英语：）
* Cornacchia（英语：）
* 整數關係（英语：）（LLL（英语：）；KZ（英语：））
* 平方求冪
* 整数平方根
* 模幂运算
* 蒙哥马利算法
* Schoof（英语：）
* 特拉亨伯格系統（英语：）

 |
|  |
| 
* *斜体*表示该算法只适用于特殊形式的数字

 |

 |