本文原标题「分治 FFT/NTT 学习笔记」,不过这容易与分治 + NTT 混淆,因此在接触到半在线卷积的概念后果断更名。

半在线卷积 I

考虑计算序列,其中由卷积得到:

是个已知序列,值已知。

求逆

首先要说,上述问题可以直接通过多项式求逆解决。设两者的生成函数。那么

因此得到

多项式求逆的复杂度为

分治卷积

分治卷积,也称分治 FFT/NTT,指将贡献通过分治转化为离线卷积,通过多项式卷积的方式计算贡献。

我们定义记号表示多项式,也就是序列的区间对应的生成函数。

另外我们定义表示多项式的每一项系数有对的对应项系数的贡献。简而言之,这描述的是对于任意,令

这样我们就可以较为严谨地描述分治卷积的算法过程。定义表示的操作。换言之计算区间的半在线卷积的贡献。

考虑分治。那么对于区间中点

  1. 先递归地调用来计算出的全部系数。
  2. 累加的贡献。
  3. 再调用来计算的全部系数。

第二步可以形式化地描述为操作

暴力执行这一操作复杂度过高。为了降低复杂度,我们首先考虑限定的区间,因为中并不是每个系数都能贡献到。简单计算一下可以发现该操作等价于

区间范围计算过程

考虑的区间端点。那么设对应的区间是。则有

这样可以得到(一些小的边界情况就不考虑了)。

因此对应的区间就是, 也就是

由于的系数已经通过第一步的递归计算得到,那么我们可以计算的多项式卷积来得到对的贡献。

计算这个卷积的复杂度是。因此整个分治卷积的总时间复杂度为

半在线卷积 II1

已知,设。且

序列。

与上一个半在线卷积不同的是,也是半在线的。这时我们可能会想到在分治卷积的过程中同时计算

假设我们已经计算好,接下来考虑的贡献。

错误策略

如果仍然采用的分治卷积方式。

那么当时就有

但是还没有被正确地计算出来,因此这样计算是不对的。

这时我们需要利用分治卷积的一个性质:若令,那么在分治过程中若,那么一定有

证明

考虑递归到的过程。则显然有

也就是说原策略在的情况是对的。所以我们得特殊处理的情况。我们将原策略修改一下:

时:

  • 执行。此时其他部分少掉的贡献是

时:

  • 首先执行原策略
  • 然后我们补上时缺失的贡献,也就是

这样就可以使用分治卷积来计算了。总时间复杂度仍为

半在线卷积 III1

对于多项式和已知的多项式,有

其中已知。求

仍然是考虑分治卷积。假设我们已经算出,则的贡献,有两种描述方式!

方法一

我们将贡献描述为

请注意代表的含义是不一样的。

如果要利用暴力地计算,那么可以执行。复杂度是,显然不能接受。

这时我们仍然考虑分治卷积的区间性质。

时我们直接执行上述操作,复杂度是的。

否则,由于,因此,换言之没有任何贡献。于是上述操作可以拆成

后者其实就是的贡献,是个半在线卷积的形式。因此我们设多项式,然后同时分治卷积地计算即可。

方法二

,那么贡献仍描述为

,那么我们将贡献描述为

原因是,因此,所以我们可以将拆分为。写成生成函数的形式就得到了上式。

进一步约束范围可以得到。这样就可以计算贡献了。

总时间复杂度

方法二的应用参考 UOJ50 链式反应

不等关系

给定一个字符串,仅包含<>两种字符。

计算有多少长度为的排列满足的关系是。答案对取模。

考虑容斥,大于 = 无限制 - 小于。考虑我们将长度为的排列分成段,每一段的长度为,段内的关系都是小于,段与段之间的关系是无限制。则这样的排列的方案数是

把容斥系数放在 DP 的式子里即可。设表示排列的前个数的方案数除以的结果。答案即为。设。特别地,我们定义

其中

直接 DP,复杂度。我们稍微变换一下式子

。这样就可以分治卷积了。

代码

1. https://www.luogu.com.cn/blog/command-block/ban-zai-xian-juan-ji-xiao-ji