本文原标题「分治 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 ↩