分治NTT
分治NTT
前置知识
多项式定义,运算以及所有相关算法。
例题1
现有一转移式形如 \(f(i)=\sum _{j=0} ^{i} f(j)g(i-j)\),其中终止条件 \(f(0)=1\)。由于 \(f(j)g(i-j)\) 是卷积的形式,不难想到NTT。但是前面的 \(f(j)\) 会对后面的 \(f(i)\) 做贡献,所以不能直接NTT。
这种前面的操作只会对后面的查询产生贡献的问题,不难想到CDQ分治这个算法。所以我们考虑分治NTT。
具体来说,我们需要将问题分为三部分:递归解决左半的问题,计算左半对右半的贡献,递归解决右半的问题。
考虑左半对右半的贡献是什么。设我们当前解决的问题是 \(l\) 到 \(r\) 区间的,定义 \(mid=\frac {l+r}{2}\)。那么左半对右半的贡献 \(f(i)=\sum _{j=l}^{mid} f(j)g(i-j)\)。\(f(j)g(i-j)\) 是一个卷积的形式,所以可以直接把 \(f\) 的 \(l\) 到 \(mid\),\(g\) 的 \(0\) 到 \(r-l\) 提出来,对这一部分进行NTT。
时间复杂度为 \(O(n\log^2_{}{n})\)。证明与CDQ分治的时间复杂度类似。
例题2
现需要求一多项式 \(F(x)=\prod _{i=1} ^m (x^{a_i}+1)\)。其中 \(\sum a_i=n\)。如果我们从左往右依次卷积,最坏时间复杂度为 \(O(n^2\log n)\)。究其根本是因为我们做卷积的多项式长度之和为 \(\sum a_i(m-i+1)\) 也就是 \(n^2\) 级别的。
考虑分治,先将编号为 \(l\) 到 \(mid\) ,\(mid+1\) 到 \(r\) 的分别递归卷积,然后将两部分卷积起来。递归树的深度是 \(\log n\) 级别的,这也就意味着每个式子只会被计算 \(\log n\) 次,总时间复杂度就变成了 \(O(n\log^2 n)\)。
例题3
现在需要求出 \(\sum _{i=1} ^n \frac{1}{1-a_ix}\)。直接多项式求逆再加是肯定不行的。考虑如下两种方法。
法1
考虑现有多项式 \(A\),\(B\),\(C\),\(D\)。则 \(\frac{A}{B} + \frac{C}{D}=\frac{AD+BC}{BD}\)。所以可以直接卷积求出 \(AD\),\(BC\),\(BD\)。时间复杂度 \(O(n^2\log n)\) ,用上面例题2的方法分治NTT求解可以使时间复杂度降为 \(O(n \log^2 n)\)。
法2
考虑 \([\ln(1-a_ix)]'=\frac{-a_i}{1-a_ix}\),等式两边同时乘上 \(x\) 得到 \(x[\ln(1-a_ix)]'=\frac{-a_ix}{1-a_ix}=1-\frac{1}{1-a_ix}\) 。则 \(\sum _{i=1}^{n} x[\ln(1-a_ix)]'=n-\sum _{i=1}^n \frac{1}{1-a_ix}\)。所以我们只需要把左边的式子求出来就好了。
因为 \([f(x)+g(x)]'=f'(x)+g'(x)\) 所以左边的式子就是 \(x [\sum _{i=1}^n \ln(1-a_ix)]'\) 则为 \(x \{\ln[\prod _{i=1}^n(1-a_ix)] \}'\) 。直接用例题2的分治NTT求解 \(\prod _{i=1}^n (1-a_ix)\) 然后多项式 \(\ln\),多项式求导即可。时间复杂度 \(O(n \log^2n)\)。

浙公网安备 33010602011771号