哈集幂难被掳夺

· · 算法·理论

黎明前的巧克力

题意

原题链接。

选出长度为 n 的序列 a 中的两个可空不交子序列,使得这两个子序列的异或和相等。0\le a_i<2^V

做法

考虑集合幂级数。我们要选出一个子序列,这个子序列的异或和为 0,子序列内部的数可以选择选入第一个子序列或者第二个子序列。

不难发现这是在求 \displaystyle [x^0]\prod_{i=1}^n(1+2x^{a_i})

由于 FWT 的性质不足,考虑一种暴力也就是做 n 次 FWT 后点乘再 IFWT。

考虑 FWT 的定义式:\displaystyle \hat{F}_i=\sum_{j=0}^{2^V-1}F_j(-1)^{i\cap j}

容易发现对 1+2x^{a_i} 做 FWT 后只有两种数也就是 -13

考虑点乘后的,IFWT 前的序列中,每一项的贡献为 (-1)^{z}3^{n-z}

考虑算出 z。我们把所有 a_i 放到一个序列 b 中做 FWT,根据 \hat{b}_i 的值算出 z_i 即可。

总结

这个做法还可以用到 Triple 上。

稍微拓展一下就是 goods。

我的 XOR 卷积人生

题意

原题链接。

你要在两个长度为 2^n 的矩阵序列上做 xor 卷积,没有任何手段获取乘法逆元。

要求为 O(n^22^n)

Part 1

考虑 n=1 怎么做。

对于序列 [a_0,a_1][b_0,b_1] 做异或卷积可以得到 [a_0b_0+a_1b_1,a_0b_1+a_1b_0]

考虑如何把这个过程拆分成点乘。

设计一个形式元 x,计算 (a_0+a_1x)(b_0+b_1x)

得到的结果是 a_0b_0+a_1b_0x+a_0b_1x+a_1b_1x^2

我们想要的结果是 f(x)=a_0b_0+a_1b_0x+a_0b_1x+a_1b_1

朴素的做法是设计 x^2=1,然后让 x=1,-1。这两个根为 \alpha,\beta

求出 f(\alpha),f(\beta) 后再插值还原 f

Part 2

对于 n 为任意的情况。我们设计 x^{S} 表示 \displaystyle \prod_{i\in S}x_i。所以 x 其实是一个长度为 n 的向量 [x_0,x_1,...,x_{n-1}]

设计集合幂级数 f(x)=\displaystyle \sum_{i=0}^{2^n-1} A_ix^i

我们再设计 2^n 个根 X_p。定义 X_p=\displaystyle \prod_{i=0}^{n-1}[p_i=0]\alpha+[p_i=1]\beta

代入这些根后得到 2^n 个结果 Y_p=f(X_p)。代入根的过程容易用分治加速。

得到 Y 后,插值的过程也容易用分治加速。

对于 xor 卷积,要解方程 x^2=1,根是 \alpha=1,\beta=-1

对于 or 卷积,要解方程 x^2=x,根是 \alpha=0,\beta=1

Part 3

考虑子集卷积。

要解的方程是 x^2=0,这是重根,无法插值。

设根为 \alpha=0,\beta=\epsilon。维护含有 \epsilon 的多项式即可。

插值时可以求逆。具体的,我们让 Y_0=f(0),Y_1=f(\epsilon)

拉格朗日插值得到 Y_0\dfrac{x-X_1}{X_0-X_1}+Y_1\dfrac{x-X_0}{X_1-X_0}。容易求解。

最后得到答案后再让 \epsilon\leftarrow 0 即可。

Part 4

我们让原题的 \alpha=1,\beta=\epsilon-1

此时要做多项式操作,复杂度变为 O(n^32^n)

Part 4.5

不妨把 x 平移一位,也就是 a_0+a_1(x+1-1)。我们让 a_0\leftarrow a_0+a_1,这样变成 a_0+a_1(x-1)

这个时候我们让 (x-1)^{2}=1,解得 \alpha=0,\beta=2

我们设 \beta=\epsilon,跑一遍子集卷积,最后再让 \epsilon\leftarrow 2 即可。最后再还原真正的 c_0,c_1

时间复杂度可以复用子集卷积的实现得到 O(n^22^n)

总结

这个题把 FWT 看成了一种多项式多点求值方法,把 IFWT 看成了一种多项式插值方法。是一道不可多得的好题。

3^N Minesweeper

题意

原题链接。

做法

我们来考虑用矩阵表示 FWT。

一般来讲,FWT 可以看成 \displaystyle \hat{F}_i=\sum_{j=0}^{3^n-1} c(j,i) F_j

然后我们要对这个矩阵 c 求逆来得到逆变换(IFWT)。

考虑拆出一个 3\times 3 的矩阵 c_0 表示 n=1 时的矩阵。c_1 表示 c_0 的逆矩阵。

那么我们把 c(j,i) 表示成 \displaystyle \prod_{v=0}^{n-1} c_0(j_v,i_v)

接下来证明 \displaystyle c^{-1}(j,i)=\prod_{v=0}^{n-1} c_1(j_v,i_v)

F_i=\sum_{j=0}^{3^n-1}c^{-1}(j,i)\sum_{k=0}^{3^n-1} c(k,j) F_k\\ F_i=\sum_{j=0}^{3^n-1}\left(\prod_{v=0}^{n-1} c_1(j_v,i_v)\right)\sum_{k=0}^{3^n-1} \left( \prod_{v=0}^{n-1} c_0(k_v,j_v)\right) F_k\\ F_i=\sum_{k=0}^{3^n-1} \sum_{j=0}^{3^n-1}\left(\prod_{v=0}^{n-1} c_1(j_v,i_v)\right)\left( \prod_{v=0}^{n-1} c_0(k_v,j_v)\right) F_k\\ F_i=\sum_{k=0}^{3^n-1} \sum_{j=0}^{3^n-1}I(k,j)I(j,i) F_k\\

这个显然成立。由于逆矩阵如果存在就唯一所以得解。

考虑快速计算。接下来我们引入 FWT 的矩阵形式。

\hat{F}_i=\sum_{j=0}^{3^n-1} c(j,i)F_j\\ \hat{F}_i=\sum_{j=0}^{3^n-1} \left( \prod_{v=0}^{n-1} c_0(j_v,i_v)\right)F_j\\ \hat{F}_i=\sum_{j=0}^{3^{n-1}-1} c_0(0,i_{n-1})\left( \prod_{v=0}^{n-2} c_0(j_v,i_v)\right)F_j +\sum_{j=3^{n-1}}^{2\times 3^{n-1}-1} c_0(1,i_{n-1})\left( \prod_{v=0}^{n-2} c_0(j_v,i_v)\right)F_j+\sum_{j=2\times 3^{n-1} }^{3^n-1} c_0(2,i_{n-1})\left( \prod_{v=0}^{n-2} c_0(j_v,i_v)\right)F_j \\

考虑预处理 \displaystyle F'_i=\sum_{j=0}^{3^n-1} \left( \prod_{v=0}^{n-2} c_0(j_v,i_v)\right)[j_{n-1}=i_{n-1}]F_j

这样可以得到 \hat{F}_i=c_0(0,i_v)F'_a+c_0(1,i_v)F'_b+c_0(2,i_v)F'_c。其中 a,b,c 为改变 i 的位 n-1 变为 0/1/2 后得到的三进制数。这就是 FWT。

总结

矩阵形式的 FWT 可以用来描述一些更一般的问题。

欧伊昔说了任意运算表的情况,但我不会。其实大概意思就是把每一维拆成更多矩阵但是先不写了。

集合划分计数

题意

原题链接。

在长度为 m 的序列 a 中选至多 k[0,2^n-1] 的二进制数使得他们两两的按位与为 0,按位或为 2^n-1

做法

弱化问题是“不交并”集合幂级数的 \exp。这也是最常说是集合幂级数的运算。

先理解一下 O(n^22^n)\exp 这件事情。

我们设计了一个新的元 y。这其实就是之前说的 \epsilon

但是现在换个角度,我们先对 x 这一维做 or-FWT。

什么意思?就是每一维代入 01 做点求值就懂了。

这个时候我们 y 这一元一直没有变,所以我们就是做了 n 次 or-FWT,点求值出来其实 1 代表的是当前这个维度的 y^i

这样子我们求完后就要求出 2^n 个点值的答案。这就是在 y 这一维上做一遍 \exp

然后我们再 IFWT 回去就好了。

那么这个题就是把里面的那次操作改了一下。

总结

可以逐点牛顿迭代法,但我不会。

FWT + IFWT 是一种插值方法,这个东西是有用且直观的。

总结

好多难的东西还没写,但是新年快乐!