[CF662C]Binary Table

壹、题目描述 ¶

传送门 to Luogu

贰、一些思考 ¶

这是二刷,知道这是一道 \(\tt FWT\) 的妙妙题 但是可能还是不会

关注点在 \(n\le 20\),那我们就来暴力枚举我们翻转了哪些行吧?

现在我们已知每一行的翻转状况,对于每一列,我们一定要取其最优值,有一种朴素的方案是再扫一遍每一列,判断最优情况即可。

但是这样真的可以接受吗?显然是不行的。考虑我们目前枚举的翻转行在二进制下的数为 \(s\),对于第 \(i\) 列,将其初始状态记为 \(\omega_i\),那么在 \(s\) 的变换下,实际第 \(i\) 列就是 \(\omega_i\oplus s\),换句话说,我们要求的是

\[\sum_{i=1}^m \min\{\text{bitcnt}(\omega_i\oplus s),n-\text{bitcnt}(\omega_i\oplus s)\} \]

然后我就不会了...... 二刷都不会,我真的是个废物

叁、题解 ¶

\(f(x)=\min\{\text{bitcnt}(x),n-\text{bitcnt}(x)\}\),对于一个 \(s\),我们考虑它的贡献,为

\[\sum_{i=1}^mf(\omega_i\oplus s) \]

但是这个 \(s\) 放在参数里面,有没有什么办法能把他拿出来?我们考虑在外层加上一个循环枚举 \(\omega_i\oplus s\) 的结果,那么

\[Ans=\sum_{i=1}^m\sum_{\beta=0}^{2^n-1}[\beta=\omega_i\oplus s]f(\beta) \]

可以将相同的 \(\omega_i\) 整合起来,设 \(t_x\) 为所有列中,二进制为 \(x\) 的列的个数,那么枚举 \(m\) 无用了,变成了一个 \(2^n-1\) 的枚举,即

\[Ans=\sum_{i=0}^{2^n-1}\sum_{\beta=0}^{2^n-1}[\beta=i\oplus s]f(\beta)t_{i} \]

嘿,发现了点什么没有?如果我们记 \(Ans=g(s)\),那么就有

\[g(s)=\sum_{i\oplus j=s}t_{i}f(j) \]

然后,这就变成板子了......将两个长度为 \(2^n\) 的数组用异或卷积卷起来,得到 \(g\),再在 \(g\) 中取最大值即为答案。

叁、参考代码 ¶

\(\color{red}{\text{talk is FWT, but I have no code.}}\)


肆、用到 の \(\tt trick\)

柿子中的 \(\min,\max\) 有时候都很烦,考虑把这些东西去掉,这里直接将其记为一个函数,眼不见心不烦啊......

另外,当自变量在函数之内时,此处用到的处理方法是将参数的值整体拿出来枚举,并加上一个布尔表达式,这样不影响结果。

posted @ 2021-04-08 21:47  Arextre  阅读(47)  评论(0编辑  收藏  举报