(半)在线卷积小记

前言

本文写于 2021-12-02 14:47,是上学期我研究的对于算法竞赛来说用处很小的东西。

今天想起,需要重新整理好二叉(半)在线卷积的模板,这个东西在考场上还是很有用的。

相关题目:

半在线卷积

\(H = FG\)。其中 \(G\) 的系数事先给出,\(F\) 的系数从低次到高次在线地给出,每次给出 \(F\)\(x^i\) 系数后,你需要在线地计算 \(H\)\(x^i\) 系数。

考虑分治,将区间 \([l, r)\) 分为 \(T\) 段,每段长度为 \(B = 2^k\)\[ [l=m_0, m_1), [m_1, m_2), \dots, [m_{T-1}, m_T=r) \] 要分别计算对于 \(0 \leq i < j < T\), \(F[m_i, m_{i+1})\) 对于 \(H[m_j, m_{j+1})\) 的贡献,其中 \(A[l,r)\) 表示多项式 \(A(x)\)\(x^l, x^{l+1}, \dots, x^{r-1}\) 处的系数。

显然 \(F[m_i, m_{i+1})\) 要乘上 \(G[m_j-m_{i+1}+1, m_{j+1} - m_i)\)

结果有 \(3B - 1\) 项,从 0 开始标号,取第 \(B-1\)\(2B-2\) 项,做长度为 \(2B\) 的循环卷积即可。

存储 \(F[m_i, m_{i+1})\)\(G[m_j-m_{i+1}+1, m_{j+1} - m_i)\) 的点值,需要做 \(T\) 次长度为 \(2B\) 的 DFT,两两作点乘,最后再 IDFT,单层复杂度为

\[ O(BT\log B+T^2B+B\log B) = O(n \log \frac{n}{T} + nT) \]

设总时间复杂度为 \(S(n)\),则 \[ S(n) = T\cdot S(\frac{n}{T}) + O(n\log \frac nT + nT) \]

这里复杂度不会算,但是大家都取 \(T = \log n\),然后得到 \(O\bigg(\dfrac{n \log^2 n}{\log\log n}\bigg)\)

在线卷积

\(H = FG\)\(F, G\) 的系数从低次到高次在线地给出,每次给出 \(F, G\)\(x^i\) 系数后,你需要在线地计算 \(H\)\(x^i\) 系数。

类似刚刚思路,但是进行到 > \(F[m_i, m_{i+1})\) 要乘上 \(G[m_j-m_{i+1}+1, m_{j+1} - m_i)\)

这一步时,发现了问题:如果 \(m_i=0\),那么 \(G[m_{j}, m_{j+1})\) 还没给出,无法计算。

于是这里先避开 \(F[m_i, m_{i+1}) \times G[m_{j}, m_{j+1})\) 这部分贡献不算,递归到 \([m_{j}, m_{j+1})\) 这个区间时,再把这个补上。

综上所述,对于当前区间 \([l, r)\),如果 \(l = 0\),那么需要计算 \(F[m_i, m_{i+1}) \times G[m_j-m_{i+1}+1, m_{j+1} - m_i)\);如果 \(l > 0\),那么除了 \(F[m_i, m_{i+1}) \times G[m_j-m_{i+1}+1, m_{j+1} - m_i)\) 之外,还要计算 \(G[m_i, m_{i+1}) \times F[m_j-m_{i+1}+1, m_{j+1} - m_i)\)

其余部分前面的半在线卷积完全相同。


最后修改于 2022-05-20