快速数列变换这个词怎么造出来的
在观察到 数列幂级数,快速数列变换(Fast Array Transform)及其特化 - 洛谷专栏 从 cnblogs 到 luogu 之后,作者迫不及待的准备了这份合订本(意味着这篇会出现一些链接)以对这份看起来不是很牛的文章进行评价。此前 u 群的部分聊天记录可能是这篇出现的伏笔。
感兴趣的还可以尝试拓展阅读 Convolution, In the Perspective of 3-Dimensional Tensors - Codeforces 和 2025 年集训队论文《浅谈张量及其在 OI 的运用》。
对于一些细节层面的内容等到有空的时候会继续补充。
前言:时间线
我所知道的关于最早的 FWT 的构造探索可能是 command_block 等(位运算卷积(FWT) & 集合幂级数 - 洛谷专栏)的。
总之,之后是出现了一大堆同类文章,但是都毫无意外的出现
而这种构造方式难以解释 GYM102129A Tritwise Mex 这一道题,甚至很难用来解题,因为不直观,适用范围很有限。即使如此,甚至还是被沿用下来。
在该题的题解引入了张量分析,虽然是扩展了适用范围,但是介绍不太全面。
直到在今年的 12 月 31 日所发出的 CF blog(见上)和 12 月 23 日提交,不知道什么时候传出来的的集训队论文共同抛弃了 command_block 系列的
虽然性质还是比较奇怪,但是对限制做一些人性化能够比上文更容易地解题。
但是仍然存在大量题解使用
在 u 群出现数列幂级数后,已经有对于这个限制的讨论。
但数列幂级数出现在了算法·理论里。
所以是时候来一篇对于目前我已知的、使用另一种方法的文章的合订本,来和其“对冲”了。
FMT 和高维前缀和
这部分可以不阅读,如果理解两者的关系的话。
对于求
对于
可以使用高维前缀和,按位相乘,高维差分得出
事实上,
FWT 以及一个不是很牛的扩展
参考:位运算卷积(FWT) & 集合幂级数 - 洛谷专栏,或者大量同类型的文章。
我们拿出高维前缀和的代码:
for(int i=0;i<n;++i)
for(int j=0;j<(1<<n);++j)
if(!(j>>i&1))A[j|(1<<i)]+=A[j];
考虑拓展到
可以发现,每次是对 A[j|(1<<i)] 和 A[j] 做一个线性变换。而如果只考虑一维的情况,这个线性变换明显是前缀和。
由于过程中全是线性操作,所以设结果为
于是我们可以让
模拟
依据原文的分析,我们需要有
对于
我们只需要对
上述的分析过程和代码都可以选择一篇讲解 FWT 的文章来查看。
注意到先前所给出的约束:
作者尚未弄清楚这种情况的出现,因为已经存在此方法无法解决的题目。
CF GYM102129A Tritwise Mex
求
如果上面的构造方法成立,我们应该给出
当然存在一些题解使用硬凑的方式,把输入输出改造成
4^n 大小。但是这样的复杂度是O(4^nn) 的,也不优秀。
事实上我们可以使用分治乘法。这种做法的具体定义和一些技巧见 巨大多我们 - 洛谷专栏。
这里再次给出定义:
按照最高位划分出
A_0,A_1,A_2 和B_0,B_1,B_2 。所以 $a_ib_j\to c_k$ 的贡献可以被拆成每一位。同时这里题目定义的“卷积” $$W(A,B)=\sum_{i\mathop{\mathrm{op}}j=x}A_iB_j$$ $W$ 对于 $A$ 或者 $B$ 是线性的(双线性)。因此有乘法分配律 $W(kA+B,C)=k W(A,C)+W(B,C)$,$W(A,kB+C)=k W(A,B)+W(A,C)$。 因为调用乘法,我们需要构造若干个 $D_i=W(\sum x_{i,j}A_j, \sum y_{i,j}B_j)$。这里有 $r$ 个。 最后我们要求 $C_k=\sum_{\text{op}_{i,j}=k}W(A_i,B_j)$,需要可以用 $D_i$ 加减表示。 在接下来的题目中,我们默认 $A_i,B_j$ 是一个变量,这样 $W(A_i,B_j)=A_iB_j$。但不影响推广。 关于时间复杂度分析:$T(n)=rT(n-1)+O(3^n)=O(\max\{r^n,3^nn\})$,当 $r\ge 3$ 的时候。
之后可以类似这样的人类智慧的凑。【题解】GYM-102129A-Tritwise Mex | Zerol's Notes。
可以发现,这种构造天然支持任意位运算操作。但注意,这里的算法实现依赖于分治乘法,而不是传统的变换-逆变换形式。
但中间的转移矩阵其实本质相同,并且整个算法形式可以自然转换到 变换-逆变换 形式,可以参考 P4717 题解 - 洛谷专栏 中的内容。
说了这么多还没有考虑限制条件。
考虑
a_ib_j\to c_k ,其贡献是[\text{op}_{i,j}=k] 。设最后
C_k=\sum z_{i,k}D_i 。这个算法贡献是
\sum_t x_{t,i}y_{t,j}z_{t,k} ,应该等于[\text{op}_{i,j}=k] 。
对于这个限制的人性化处理可以参考 巨大多我们 - 洛谷专栏 里提到的表示方式。
这个限制是几乎充要的,其看上去能够支持任何位运算卷积的构造(除了子集卷积以外都是显然的,后面会拓展让其进一步支持子集卷积)。
张量 CP 分解求张量秩上界的乱搞 巨大多我们 - 洛谷专栏 里提到一点,对于特定张量分解的乱搞存在一些研究者在整 (Kauers-Moosbauer) 等,当然最近的 AI 优化矩阵乘法本质也是在搞这坨。
熟悉张量的都知道,这东西是张量 CP 分解道理,而求张量秩(最小的
张量的概念在任意一个分治乘法,复杂度和乘法次数有关的分治算法中几乎能够用上,例如矩阵乘法和多项式乘法(Karatsuba 及其引申)。
子 集 卷 积
在几乎所有的题解(这里应该能几乎完全断定除作者以外的所有题解),子集卷积使用 FMT 加上一个看似割裂的占位多项式来获得操作。
事实上,这部分和张量的边界秩有关。
一种详细介绍如何将占位多项式揉到 FMT 的结构内见 P6097 题解 - 洛谷专栏,这篇题解由于题解区满了暂时没法加入。
进一步?
注意到我们的分析中,最后的限制
这启发我们输入输出本质是一致的,可以交换。
实际上,根据 Convolution, In the Perspective of 3-Dimensional Tensors - Codeforces 中的 Baur-Strassen's Algorithm 可以解释。但是其实这是极其容易理解的,根本不需要感受。
这里可以干一些有趣的事情,比如
具体使用场景:题解:P11458 [USACO24DEC] All Pairs Similarity P | 进行一个转 - 洛谷专栏
如何严格包含快速数列变换的运用场景
对于位运算
我们递归调用
注意到快速数列变换只能支持使用
对于子集卷积,我们有更好的方法能够规避额外加的“占位多项式”。或者说将占位多项式嵌入位运算卷积中更好。
对于快速 GCD/LCM 变换。只给你一维显然是会做的,直接将一维对应的
这里提到的迪利克雷前缀和 / 差分主要目的是优化
一个小东西
对于特征为
这种情况无法使用普通的 FWT 算法(因为有
但是我们仍然可以尝试摸索边界秩,利用
具体来说可以假设这个是必须的:
我们只有一个
但是这样应该是啥作用没有,需要修改
中间用了
注意
于是得到解决,时间复杂度
我宣称这题用程序爆搜都能出来这个构造。原因前面说过了。
言简意赅的总结
综上所述,数列幂级数显然是张量分解的特化,别再
倒挺想知道那么多题解都写这东西究竟有多少人在用它,感觉一用一个不吱声。