多项式幂的 18E 分块算法
草稿。。。
终于做出来一点原创的结果了。
上一篇写了 4 阶牛顿迭代,最后提到还有一个 18E 的 pow 想法。现在也写出来。
问题定义
多项式幂的定义是
g=fkmodxn,f(0)=1
最直接的做法是
g=exp(klnf).
一般来说,如果你使用的是比较朴素的 13E ln 和 17E exp,得到的就是一个 30E 的 pow 算法;如果你选择的是 SOTA 10E ln + 11.5E exp,你将收获一个 21.5E 的 pow;根据我的实践,10E ln + 14E exp 在实机上表现最好,也就是 24E 的 pow。
也有独立的 pow 算法,目前的 SOTA 是 20.25E,本文提出了一种新的 18E 的计算多项式幂的算法。
之前尝试在线卷积的时候,就有想过能不能同时维护两边的迭代式,得到更好的复杂度,本次就继续沿着这个思路取得了一些进展。
分块
建议阅读 多项式牛顿迭代的分块优化,本文引用了其不少结论。
记块长为 m,X=xm,把
f=f[0]+f[1]X+⋯,g=g[0]+g[1]X+⋯.
假设已经知道 g[0],⋯,g[s−1],现在要求 g[s]。
在前一篇 inv 的分块中,我们有一个结论,首先记 fg 在缺少 g[s] 下的卷积为 ψ,即
ψ=(f[0..s]g[0..s−1])[s]
我们有一个等式:
(fg)[s]−ψ=(f[0..s]g[0..s])[s]−(f[0..s]g[0..s−1])[s]=(f[0..s]g[s]Xs)[s]=f[0]∗g[s]modX(1)
接下来我们将在两边的迭代式考虑这两个卷积的差。
微分方程
沿用之前的记号,考虑原地微分算子 Δh=xh′(x)。
为了方便起见,我们记 Δif=X−iΔ(Xif),也就是一个平移到微分算子,有
Δ(f[0]+f[1]X+⋯)=(Δ0f[0])+(Δ1f[1])+⋯
考虑 g=fk,两边微分得到
fΔg=kgΔf
把两边同时加上一个 gΔf,写成
Δ(fg)=(k+1)gΔf
这个式子更适合分块,因为左边出现的是 fg,而最后我们要解的是 g 的新块。其分块形式为
(Δfg)[s]=(k+1)(gΔf)[s](2)
考察两侧式子缺少第 s 块的情况,我们考虑维护左侧 fg,考虑应用公式 (1),得到
(fg)[s]−ψ=f[0]g[s]modX.
对于右侧,考虑维护 gΔf,继续应用公式 (1),得到
(gΔf)[s]−ϕ=(Δf[0])g[s]modX
再考虑等式 (2),因此有
Δs(ψ+f[0]g[s])=(k+1)(ϕ+g[s]Δf[0])(modX)
接下来要把 g[s] 解出来。直接求解比较困难,两侧一边是 g[s] 另一边是 Δsg[s],消不掉。
考虑换元,令
g[s]=g[0]u.
因为 g[0]=f[0]k,所以
Δ(f[0]g[0])=f[0]Δg[0]+g[0]Δf[0]=(k+1)g[0]Δf[0].
再注意到
Δs(f[0]g[s])=Δs(f[0]g[0]u)=f[0]g[0]Δsu+uΔ(f[0]g[0])=f[0]g[0]Δsu+(k+1)g[0]uΔf[0]=f[0]g[0]Δsu+(k+1)g[s]Δf[0]
这恰好是公式 (2) 中的两项,因此
f[0]g[0]Δsu=(k+1)ϕ−Δsψ.
也就是
u=Δs−1(f[0]g[0](k+1)ϕ−Δsψ),g[s]=g[0]u.
具体过程
计算 ψ 和 ϕ 的方法与上一篇分块的方法完全相同,即计算 fg 和 gΔf 的第 s 块。由于 g 是共享的,只需要维护 f,Δf,g 的分块 DFT,再通过两次 IDFT 即可获得 ψ 和 ϕ。
具体计算流程如下:
- 假设已经求出求出 g[0]=f[0]k。
- 计算 F2m(g[0]),这里 2E 的开销被计入迭代内,故无开销。
- 计算 f[0]g[0]modX,需要 4E。
- 预处理 h=(f[0]g[0])−1 可以使用任何 6E 的算法。
- 依次计算第 s 块:
- 计算 F2m(f[s]) 和 F2m(Δsf[s]) 和 F2m(g[s−1]),开销 6E。
- 用块乘积算出 ψ,开销 2E。
- 用块乘积算出 ϕ,开销 2E。
- 计算 ρ=(k+1)ϕ−Δsψ,线性开销。
- 计算 v=hρmodX,开销 4E。
- 计算 u=Δs−1v,线性开销。
- 计算 g[s]=g[0]umodX,开销 4E。
总之,单个新块的复杂度为 18E,当块数 r→∞ 时,均摊复杂度也就是 18E。
严格的说,复杂度 T(n)⩽18E(n)+O(nlogn)。
实现与测试
性能测试取 NTT 模数 P=998244353,指数固定为 k=7,并使用 AVX2 优化。
可以看到收益比较稳定,大概快 20% 多一点,符合预期。
总结
本来只是闲暇时的瞎想,没想到越琢磨越有道理,终有此篇。也总算是做出来一点点属于自己的东西了。