FWT & FMT

CF662C

首先有一个 \(\mathcal O(2^nm)\) 的做法。

枚举每一行是否反转的状态 \(s\),记 \(g_i=\min(\operatorname{popcount}(i),n-\operatorname{popcount}(i))\)\(t_i\) 表示第 \(i\) 列的状态。

则答案为 \(\min_s{\sum_{i=1}^m g_{s\operatorname{xor} t_i}}\)

发现这个东西很难处理,记 \(f_i\) 表示 \(t_j=i\) 的个数。

则答案为 \(\min_s{\sum_{i=1}^{2^n-1} f_ig_{s\operatorname{xor} i}}\)

发现有 \(s \operatorname{xor} i \operatorname{xor} i=0\),原式可以写作:

\[\min_s{\sum_{i\operatorname{xor}j = s} g_i f_j} \]

显然是一个标准的 FWT 形式。

直接做就可以了。

Submission

Cnoi2019 人形演舞

有结论 \(\operatorname{SG}(i)=i-2^{\operatorname{highbit}(i)}+1\)

证明:

可以在 \(\mathcal O(m\log m)\) 复杂度内求出所有 \(\operatorname{SG}\) 值。

\(c_i\) 表示 \(\operatorname{SG}(j)=i\) 的个数。

选择 \(i\) 个数使它们的异或和为 \(j\) 的方案数记为 \(f_{i,j}\),则有转移 \(f_{i,j}=\sum_{a\operatorname{xor} b=j} c_bf_{i-1,a}\),答案即为 \(f_{|V|,i\ne 0}\)

这样的话,发现每次都可以进行 FWT,但是效率不够优秀。

可以先 FWT 一次,做快速幂 \(m\) 次,最后 FWT 回来即可。

这部分的时间复杂度为 \(\mathcal O(m \log |V|)\)

综上,总的时间复杂度为 \(\mathcal O(m \log m+m \log |V|)\)

Submission

posted @ 2024-05-26 17:00  WhisperingWillow  阅读(27)  评论(0)    收藏  举报