数学总结 6(FFT、NTT、卷积)
一、前置知识
快速傅里叶变换 FFT
快速数论变换 NTT
快速沃尔什变换 FWT
二、常见应用
例 1:ABC392G Fine Triplets
这场 ABC 我好像被 G 题创飞了来着。
不妨移项得 \(A+C=2B\),这是一个跟值有关的式子,所以考虑对每一个值记录一个桶表示这个数是否出现,设它为 \(c_i\)。
考虑枚举 \(B\) 计算答案:设 \(f_i\) 表示能拼凑出 \(2i\) 的方案数,则有 \(f_i = c_i \sum\limits_{j=1}^{2i-1} c_j \times c_{2i-j}\)。
这个系数 \(2\) 很不自然,但不难发现后半部分是一个卷积形式。
所以可以设 \(f_i= \sum\limits_{j=0}^{i} c_j \times c_{i-j}\),查询 \(f_{2i}\) 即可。
但最终答案要 \(-1\) 后 \(\div 2\),因为要扣掉 \(i+i=2i\) 的情况,以及钦定 \(A \lt C\)。
例 2:洛谷 P3338 ZJOI2014 力
还是挺好想的。
这个式子一眼先分为前后两部分讨论,设它们算出来分别是 \(h1_i, h2_i\)。
然后需要构造参与卷积的函数了,设分别为 \(f,g\)。
不难想到 \(f(j) = q_j, g(j) = \frac{1}{j^2}\)。
所以有:
前者是卷积板子,直接胡一下就过去了。
后者由于 \(i-j\) 是负数,所以加上偏移量 \(n\),最后答案改成 \(h2_{i+n}\) 就好了。
一直以为三次变两次优化是神一样的存在。对于我这种大常数选手简直是救星。
然而这题卡精度,三步并两步会造成精度丢失。
例 3:洛谷 P3723 AH2017/HNOI2017 礼物
这也是一道比较简单的题目。
首先看到完全平方公式,很难不想到分离贡献。
\((x-y)^2 = x^2+y^2 - 2xy\),注意到前面是定值,后面是乘积。
这启发我们把它搬到序列上看……
后者看上去很像卷积!把 \(y\) 反转一下就成了 \(\sum\limits_{i=1}^{n} x_i y_{n-i+1}\)。
考虑到 \(c\) 的范围很小(\(\leq 100\)),所以貌似可以直接枚举 \(c\),暴力计算 \(a,b\) 之后卷积。
NTT 优化,复杂度 \(O(mn \log n)\)。
理论可过,但常数大 QwQ。被卡到 70pts 了。
考虑优化,但发现并没有办法优化……
那就从头推吧,把 \(c\) 也扔进去推(现在钦定 \(c \in [-m, m]\))。
拍到序列上。
之前做法的瓶颈在于对每个 \(c\) 都要卷一次,但现在卷积部分和 \(c\) 无关了!
复杂度 \(O(nc + n \log n)\)。
很好奇为什么几乎所有题解都是一开始就注意到要把 \(c\) 放进去推……
例 4:ARC185C Sum of Three Integers
简单题,但是细节硬控两小时。
并不难想到先特判掉简单 Case:例如 \(3x = S\) 的情况和 \(2x+y=S\) 的情况。
注意判断 \(2x+y=S\) 的时候 \(x \not= 2\)。
然后枚举 \(i\),求是否有 \(j+k=S-i\),由于 \(j+k\) 长得很卷积所以直接 NTT 预处理一下就行了,注意由于特判掉 Corner Case 现在需要满足 \(i \not= j \not= k\)。
然后暴力扫即可。
三、分治 FFT/NTT
例 5:ABC352G Socks 3
或许是上上周概率与期望做多了,现在一看到这题就想到拆贡献。
具体地,求每种袜子被配对的期望,然后不太好搞还要怎么容斥算一下。
结果全乱了,事实上可以从期望的定义出发拆贡献:
设 \(g_i\) 表示选 \(i\) 次仍然没有选出重复袜子的概率。
则答案为 \(1+\sum\limits_{i=1}^{n} g_i\)。
这个式子大概就是在说 \(\geq 1\) 的概率加上 \(\geq 2\) 的概率加上……这样一直加下去。
由于每个事情只有 \(0\) 或 \(1\)(发生或不发生)两种状态,所以期望等于概率。
\(+1\) 是因为要至少再选一个才能重复。
考虑求 \(g_i\),类似于容斥的题目,转化为一个 \(\geq x\) 的形式之后做 DP。
具体地设 \(dp_{i,j}\) 表示前 \(i\) 种颜色,选出 \(j\) 种,不重复的方案数,则 \(g_i = \displaystyle \binom{\sum\limits a_j}{dp_{n}^{i}}\)。
不难写出转移 \(dp_{i,j} = dp_{i-1,j-1} a_i + dp_{i-1,j}\)。
然后就是神秘 Poly 优化转移了。
考虑把 DP 数组看作多项式,一个 \(a_i\) 的加入看作乘上一个多项式 \(a_i x + 1\)。
于是就可以在原 DP 数组的基础上不断卷上新的多项式了,复杂度很高贵不细算了。
这时候很难注意到可以分治,因为多项式乘法具有结合律。
设 solve(l, r)
表示 \([l,r]\) 多项式的乘积,每次合并 \([l,mid]\) 和 \([mid+1,r]\) 两部分的多项式即可,模数 \(998244353\) 提示得很明显可以 NTT 合并。
所以总复杂度是 \(O(n \log^2 n)\)。
其实这类 trick 叫做分治 FFT/NTT。
例 6:ABC267H Odd Sum
和上一题类似,这题也是用多项式优化 DP 转移。
事实上,01 背包中一个 \(a\) 体积的物体可以看作一个 \(1+x^a\) 的多项式,所有多项式乘积的 \(m\) 次项就是选元素和为 \(m\) 的方案数。
一样地,不能直接暴力把多项式相乘,但是每一位的多项式都较小,所以可以分治 NTT。
然而这题要求求出选奇数个物品,既然是奇偶分开做那就考虑类似容斥:再求一下 \(1-x^a\) 的多项式乘积。
这样奇数项是减,偶数项是加,只要用之前的答案减去现在的答案,就是奇数个的两倍了。
例 7:ABC247Ex Rearranging Problem
洛谷翻译得很抽象……
给定一个长度为 \(n\) 的序列 \(c\),现在你有一个排列 \(p\),初始 \(p_i = i\),进行 \(k\) 次操作,每次可以交换 \(p_i, p_j\)。
问经过 \(k\) 次交换之后有多少种排列 \(p'\) 满足 \(c_{p'_i} = c_i\)。
换个说法,就是每次可以交换 \(c_i, c_j\),问有多少种交换后的下标对应关系使得 \(c\) 和原来一样。
并不难想到将 \(i \to p_i\) 这样连边,都老套路了。
然后一个长度为 \(len\) 的环就至少需要 \(len-1\) 步还原,具体地随便拿一个环中点作为“中转站”,将所有数交换到这里再交换去对应的位置。
另外一个显然的观察是,最少交换次数的奇偶性和 \(m\) 相同,多出来的部分一直重复交换两个位置即可抵消掉。
基于这两个观察,怎么暴力怎么来,先枚举排列 \(p\) 再通过性质 1 算出至少需要多少次,根据性质 2 的奇偶性判断是否要累加进答案。
这么做有很大的优化空间,显然可以 DP:
设 \(dp_{i,j}\) 表示前 \(i\) 个点,用了 \(j\) 次交换的方案数。
看上去有点复杂,主要原因是 \(j\) 次交换不好刻画,还需要枚举 \(i\) 和哪些点在一个环中。
所以改设 \(dp_{i,j}\) 表示前 \(i\) 个点,构成 \(j\) 个环的方案数。记 \(count(i)\) 表示 \([1,i-1]\) 这些点中和 \(i\) 颜色相同的点数。
不难写出转移方程:
又是多项式优化 DP 的经典形式,将 \(i\) 点看成多项式 \((1+ count(i) x)\) 做分治 NTT 即可。
例 8:ABC213H Stroll
题目翻译提示得太多了,差评。
首先不难设 \(f_{i, u}\) 表示走到 \(u\) 点,多项式次数为 \(i\) 的方案数,则有:
卷积形式,想到 FFT,不妨换一个角度看待转移式:
这样还是只能一位一位转移,很麻烦。
怎样用 FFT 快速转移?事实上就是一次转移多个,即分治 FFT。
具体地,对次数这一维度分治,每次计算 \([l, mid]\) 对 \([mid+1, r]\) 的贡献,即 \([l, mid]\) 这一段集体卷上 \(P_{u, v}\)。
最后观察模数决定使用 NTT。
事实上分治 FFT 本质上就是 CDQ 分治。
四、结合字符串
例 9:洛谷 P4173 残缺的字符串
说多了都是玄学。
FFT/NTT 强如怪物,甚至可以和字符串结合。
考虑没有 *
字符怎么做,显然是 KMP 板子。
假设已经知道这题需要使用 FFT/NTT,那肯定要先把它转化成数学式再考虑怎么卷。
假设现在 \(S: [k,k+m-1]\) 匹配 \(T: [1,m]\),则需要满足:
因为如果只是做差的累加,可以构造出两个字符串它们所含字母相同但任意排列,这样字符串是不匹配的,但等式成立。
如果加绝对值又没有任何优化的道理,所以改为平方,还能顺便带一个乘积形式出来。
考虑反转 \(T\) 字符串:
前面两个是好维护的,至于最后一个又是卷积形式,FFT/NTT 大法好。
如果加入了 *
字符呢?
相当于无论对面给出什么字符,这一项都为 \(0\)。
所以给 *
字符赋值为 \(0\),修改判定式为:
展开得:
三部分求和都是卷积形式,FFT/NTT 爽飞了,复杂度 \(O(n \log n)\)。