CF1605F PalindORme

发布时间 2023-07-20 18:19:39作者: Ender_32k

不知道是怎么想到的。ntf 实在是不平凡的。/bx/bx/bx

你考虑如何判断一个序列是 \(\text{good}\) 的。设重排后序列 \(t_i\) 前缀 \([1,i]\) 和后缀 \([n-i+1,n]\) 按位或等于 \(w_1\)\([1,i+1]\)\([n-i,n]\) 按位或等于 \(w_2\)。不难发现 \(w_1\subseteq w_2\),这说明 \(w_2\)\(w_1\)对称差对应的那些位上,\(t_{i+1}\)\(t_{n-i}\) 均为 \(1\)。于是扔掉顺序,就变成了 \(b_i\) 里面任取两个数 \(x,y\),令 \(x',y'\) 为它们去掉当前按位或值 \(V\)\(1\) 的位的值,那么 \(x'=y'\),再将 \(V\gets V\text{or}\ x'\)

合法的序列一定会判断合法,因为每步中满足条件的 \(x,y\),如果它们没有被选,那么接下来选数时 \(x,y\) 仍然合法。并且一定可以从一个不合法的序列中拆出一个合法的子序列,而且去掉这个子序列的或和为 \(1\) 的位之后,剩下来的数互不相同

为了避免算重,如果剩下的数中有 \(0\),我们将其算进合法子序列内。

然后就可以数数了。设 \(dp_{i,j}\) 为长度为 \(i\),按位或的 \(\text{popcount}\)\(j\)不合法序列的方案数。答案枚举 \(j\) 求和即可。每次转移就枚举其合法子序列的长度以及值域(因为合法子序列的或值上的 \(1\) 可以全部去除),显然:

\[dp_{i,j}=\sum\limits_{p\in [0,i),q\in [0,j)}(g_{p,q}-dp_{p,q})\dbinom{i}{p}\dbinom{j}{q}2^{(i-p)q}f_{i-p,j-q} \]

其中 \(g_{i,j}\) 表示长度 \(i\),值域 \([0,2^j)\) 的序列,按位或和为 \(2^j-1\) 的序列个数。\(f_{i,j}\) 表示长度 \(i\),值域 \([1,2^j)\) 的序列,每个位置上的值互不相同,按位或和为 \(2^j-1\) 的序列个数。\(g_{p,q}-dp_{p,q}\) 就是合法子序列的个数,然后任取 \(p\) 个位置和 \(q\) 个二进制位。最后要求 \(i-p\) 个数要互不相同,而且对于 \(V\)\(1\) 的位,不合法的部分的数可以任选,所以乘上 \(2^{(i-p)q}\)

至于如何计算 \(f,g\),根据二项式反演(钦定一些位为 \(1\)):

\[f_{i,j}=\sum\limits_{k=0}^j\dbinom{j}{k}(-1)^{j-k}(2^k-1)^{\underline{i}} \]

\[g_{i,j}=\sum\limits_{k=0}^j\dbinom{j}{k}(-1)^{j-k}(2^k)^i \]

做完了,复杂度 \(O(n^2k^2)\)

评测记录。


upd : 详细证一下最后那个式子。

考虑计算 \(g\),首先令 \(t_{i,j}\) 为长度 \(i\),值域 \(2^{j}-1\) 随便选的方案。显然 \(t_{i,j}=2^{ij}\)

考虑选出 \(k\) 位,使得或起来后这些位为 \(1\),其它全是 \(0\)。去掉其它位后,只剩 \(k\) 位,所以方案数就是 \(g_{i,k}\)

那么枚举 \(k\)

\[t_{i,j}=\sum\limits_{k=0}^j\dbinom{j}{k}g_{i,k} \]

其实本质是容斥,二项式反演即可。\(f\) 同理。