编程语言
首页 > 编程语言> > pohlig-hellman算法讲解(有例子)

pohlig-hellman算法讲解(有例子)

作者:互联网

写在前面

一切都要从去年8月的多校开始说起。
笔者在多校某场比赛中,遇到一个离散对数的题:HDU 6632
给定a,b,p(pprime,65537p1e18,2a,bp1p12(/)3)a,b,p(p∈prime,65537\leq p \leq 1e18,2\leq a,b\leq p-1且p-1的质因子只能由2(和/或)3组成)a,b,p(p∈prime,65537≤p≤1e18,2≤a,b≤p−1且p−1的质因子只能由2(和/或)3组成),求
                                              axb(mod p)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ a^x\equiv b(mod\ p)                                              ax≡b(mod p)
的最小正整数解,若无解则输出1-1−1。

因为质数ppp很大,且通常使用的BSGSBSGSBSGS复杂度为O(n)O(\sqrt n)O(n​),显然无法通过正常方法解题。于是很理所应当地翻车了。
随后出题人给的题解中提到了 pohlig-hellman算法,想去学,但国内对于该算法的相关资料实在是少之又少。于是在理应不存在的404网站们找到了相关视频学习后才醒悟(一醒就是半年,咕咕咕)。于是决定整理一下这个问题。
注:笔者是一名十八线蒟蒻ACMer,因此下列文章可能有许多细节上的问题,请您指正,我将尽快回复和改正,非常感谢!

前置技能

快速幂
基础数论知识
欧拉函数
中国剩余定理(CRT)
质因子分解

pohlig-hellman算法

需要注意的是,pohlig-hellman算法的复杂度在一般情况下比BSGSBSGSBSGS高!
因此,使用pohlig-hellman的场合只能是较为特殊的情况。
p是质数,且p-1包含的质因子较少&较小。
(p不是质数有待补充。)
BSGSBSGSBSGS算法一样,pohlig-hellman算法也是用于解决离散对数问题(也有很多文献提到是解决椭圆曲线之类的)。
即给定a,b,p,求axb(mod p)a^x \equiv b(mod\ p)ax≡b(mod p)。
在开始讲算法前,首先要提一下欧拉定理。

(a,p)=1,aφ(p)1(mod p)()(a,p)=1,那么a^{φ(p)} \equiv1(mod\ p)······(*)(a,p)=1,那么aφ(p)≡1(mod p)⋅⋅⋅⋅⋅⋅(∗)

证明略。
如果ppp是质数,那φ(p)=p1φ(p)=p-1φ(p)=p−1,即费马小定理。
接下来,开始将pohlig-hellman算法的步骤。
以下步骤建议读者自行手写一遍!
以下步骤建议读者自行手写一遍!
以下步骤建议读者自行手写一遍!
重要的话说三遍!

1.将φφφ(p)(p)(p)=p-1质因子分解
p1=p1k1p2k2...pmkm(m)即p-1=p^{k_1}_1p^{k_2}_2...p^{k_m}_m(m为质因子个数)即p−1=p1k1​​p2k2​​...pmkm​​(m为质因子个数)

2.对于每个质因子pip_ipi​,列出方程
x=pi0a0pi1a1pi2a2...piki1aki1(mod piki)x=p^0_ia_0*p^1_ia_1*p^2_ia_2...*p^{k_{i-1}}_ia_{k_{i-1}}(mod\ p_i^{k_i})x=pi0​a0​∗pi1​a1​∗pi2​a2​...∗piki−1​​aki−1​​(mod piki​​)
(即把x写成pip_ipi​进制,每个系数都小于pip_ipi​)。

3.r=1,(ax)p1pirbp1pir(mod p)令r=1,求(a^x)^{\frac{p-1}{p_i^r}}\equiv b^{\frac{p-1}{p_i^r}}(mod\ p)令r=1,求(ax)pir​p−1​≡bpir​p−1​(mod p)
(注意这个p1pir{\frac{p-1}{p_i^r}}pir​p−1​,这是我们求出aia_iai​各项系数的关键!)

4.展开xxx,得到(api0a0pi1a1pi2a2...piki1aki1)p1pirbp1pir(mod p)(a^{p^0_ia_0*p^1_ia_1*p^2_ia_2...*p^{k_{i-1}}_ia_{k_{i-1}}})^{\frac{p-1}{p_i^r}}\equiv b^{\frac{p-1}{p_i^r}}(mod\ p)(api0​a0​∗pi1​a1​∗pi2​a2​...∗piki−1​​aki−1​​)pir​p−1​≡bpir​p−1​(mod p)

5.展开,得(以下以r=1为例)
aa0p1pia(p1)a1(ap1)pa2(ap1)p2a3...(ap1)p(ki2)aki1bp1pir(mod p)a^{a_0*\frac{p-1}{p_i}}*a^{(p-1)a_1}*(a^{p-1})^{pa_2}*(a^{p-1})^{p^2a_3}...(a^{p-1})^{p^{(k_{i}-2)}a_{k_{i-1}}}\equiv b^{\frac{p-1}{p_i^r}}(mod\ p)aa0​∗pi​p−1​∗a(p−1)a1​∗(ap−1)pa2​∗(ap−1)p2a3​...(ap−1)p(ki​−2)aki−1​​≡bpir​p−1​(mod p)

6.注意到从第二项开始,后面每一项都是1(因为由欧拉定理得ap11(mod p)a^{p-1}\equiv1(mod\ p)ap−1≡1(mod p),1的任何次方都是1),故我们可以得到式子

aa0p1pibp1pir(mod p)a^{a_0*\frac{p-1}{p_i}} \equiv b^{\frac{p-1}{p_i^r}}(mod\ p)aa0​∗pi​p−1​≡bpir​p−1​(mod p)
因为a_i的所有系数∈[0,pi1][0,p_i-1][0,pi​−1](前文提到了pip_ipi​进制),故可以在O(pi)O(p_i)O(pi​)的时间内暴力求出a0a_0a0​。

7.得到a0a_0a0​后,令r=r+1r=r+1r=r+1,回到步骤3。
直到所有a_i被求出后,可得到:
x=pi0a0pi1a1pi2a2...piki1aki1(mod piki)x=p^0_ia_0*p^1_ia_1*p^2_ia_2...*p^{k_{i-1}}_ia_{k_{i-1}}(mod\ p_i^{k_i})。x=pi0​a0​∗pi1​a1​∗pi2​a2​...∗piki−1​​aki−1​​(mod piki​​)。
(p)(注意模数不是p!)(注意模数不是p!)

8.在算出m个关于x的式子后,来一发CRT(中国剩余定理)即可(不需要扩展CRT,因为模数互质)。
需要注意!如果这组方程在CRT中无解,则说明原方程无解!!!

举例

下面,我们通过一个例子来帮助理解以上的步骤。
eg: 7x12(mod 41)7^x\equiv12(mod\ 41)7x≡12(mod 41)
解:首先分解φ(41)=40=235φ(41)=40=2^35。φ(41)=40=235。

对于质因子2,我们首先列出方程
x=20a021a122a2(ai[0,1])x=2^0a_0*2^1a_1*2^2a_2(a_i∈[0,1])x=20a0​∗21a1​∗22a2​(ai​∈[0,1])

在等式两边同乘以p12=20\frac{p-1}{2}=202p−1​=20,得

7x201220(mod 41)7^{x^{20}}\equiv 12^{20}(mod\ 41)。7x20≡1220(mod 41)。

xxx展开,得

7(20a021a122a2)201220(mod 41)7^{(2^0a_0*2^1a_1*2^2a_2)^{20}}\equiv 12^{20}(mod\ 41)7(20a0​∗21a1​∗22a2​)20≡1220(mod 41)

化简,得

720a0740a17802a1220(mod 41)7^{20a_0}*7^{40a_1}*7^{80^a_2}*\equiv 12^{20}(mod\ 41)720a0​∗740a1​∗7802a​∗≡1220(mod 41)

由费马小定理/欧拉定理得后面两项都是1,故:

720a01220(mod 41)7^{20a_0} \equiv 12^{20}(mod\ 41)720a0​≡1220(mod 41)

快速幂优化,得

40a040(mod 41)40^{a_{0}}\equiv 40(mod\ 41)40a0​≡40(mod 41)

[0,1][0,1][0,1]内枚举a0a_0a0​,得到a0=1a_0=1。a0​=1。

有了a1a_1a1​后,我们将原式同乘以p122=10\frac{p-1}{2^2}=1022p−1​=10,得到7x101210(mod 41)7^{x^{10}}\equiv 12^{10}(mod\ 41)。7x10≡1210(mod 41)。

重复上述步骤,得

7(121a122a2)101210(mod 41)7^{(1*2^1a_1*2^2a_2)^{10}}\equiv 12^{10}(mod\ 41)7(1∗21a1​∗22a2​)10≡1210(mod 41)

化简,得

710720a1740a21210(mod 41)7^{10}*7^{20a_1}*7^{40a_2}\equiv 12^{10}(mod\ 41)710∗720a1​∗740a2​≡1210(mod 41)

同样道理,后面一项是1,得

710720a11210(mod 41)7^{10}*7^{20^{a_1}}\equiv 12^{10}(mod\ 41)710∗720a1​≡1210(mod 41)

快速幂优化,得

940a19(mod 41)9*40^{a_1}\equiv9(mod\ 41)9∗40a1​≡9(mod 41)

[0,1][0,1][0,1]内枚举a1a_1a1​,得a1=0a_1=0。a1​=0。

同理我们得到a2=1a_2=1a2​=1,于是x201+210+2215(mod 8)x\equiv2^0*1+2^1*0+2^2*1\equiv5(mod\ 8)x≡20∗1+21∗0+22∗1≡5(mod 8)

x5(mod 8)即x\equiv5(mod\ 8)即x≡5(mod 8)

对于质因子555,同理,设x=50a0(ai[0,4])x=5^0a_0(a_i∈[0,4])x=50a0​(ai​∈[0,4]),得到a0=3a_0=3a0​=3,即x=3(mod 5)x=3(mod\ 5)。x=3(mod 5)。
综上所述,我们得到:
{x5(mod 8)x3(mod 5)\begin{cases} x\equiv 5(mod\ 8)\\ x\equiv 3(mod\ 5)\\ \end{cases} {x≡5(mod 8)x≡3(mod 5)​
由中国剩余定理可以得到x13(mod 40)x\equiv13(mod\ 40)。x≡13(mod 40)。

对该算法的理解&复杂度计算

个人认为,pohlig-hellman是对欧拉定理深度理解后的一种体现,先是对于每个质因子qiq_iqi​,将其表示成qiq_iqi​进制的数字,为了便于后面不断地在等式两边同乘(p1)/pir(p-1)/p_i^r(p−1)/pir​来使得部分项变成1消去,从而得到各项系数,最后CRT求解。
复杂度计算:
ω(n)\omega (n)ω(n)为nnn的质因子个数,Ω(n)Ω(n)Ω(n)定为每个质因数的幂次之和,
(对于420=22357,ω(n)=4,Ω(n)=2+1+1+1=5420=2^2*3*5*7,\omega (n)=4, \Omega(n)=2+1+1+1=5420=22∗3∗5∗7,ω(n)=4,Ω(n)=2+1+1+1=5)

首先,质因子分解需要O(Ω(n))O(\Omega(n))O(Ω(n))(原本是要先欧拉筛出质数,再质因子分解,但毕竟p-1的质因子很少时才能使用该算法(通常只有2,3,5,7),因此可以直接事先处理出来)。

其次,算出各类系数的复杂度为O(logn(Ω(n)))O(logn*(\Omega(n)))O(logn∗(Ω(n)))(每一个质因子系数是从0~对应次方-1的,再算上快速幂的复杂度)。

最后,还有中国剩余定理(CRT),其复杂度为O((ω(n)logω(n)))O((\omega(n)log\omega(n)))O((ω(n)logω(n)))(CRT的复杂度有待确认)

综上,总复杂度为O(Ω(n)+lognΩ(n)+ω(n)logω(n))O(\Omega(n)+logn*\Omega(n)+\omega(n)log\omega(n))O(Ω(n)+logn∗Ω(n)+ω(n)logω(n))。

这也就是为什么,当p1p-1p−1的质因子又小又少时,pohlig-hellman算法远远优于BSGS的原因。

代码

先咕咕咕,年后来写。好像CSDN上有别人写的来着…

后记

写这篇文章的动机很简单:我没看懂国内关于pohlig-hellman算法的文章(肯定是我语文差),因此在某些网站上学懂之后想着自己写一篇文章,一来是方便日后复习,二来帮助下和我语文一样差的程序猿…
其实p不是质数时,也是可适用该算法,只是笔者还需要一些时间来确认一些细节问题,故先咕咕咕,日后补上。
DrGilbert 2020.1.21

DrGilbert 发布了8 篇原创文章 · 获赞 17 · 访问量 1706 私信 关注

标签:...,hellman,41,pohlig,因子,讲解,20,mod,equiv
来源: https://blog.csdn.net/oampamp1/article/details/104061969