7.11dp by 一休哥777 orz
P2051
在一个 $n\times m$ 的棋盘上放置若干个互不攻击的炮,求摆放的方案数。$n,m\le100$。
首先发现炮不能互相攻击等价于每行每列最多有 $2$ 个炮。
考虑设 dp 状态 $dp_{i,j,k}$ 表示当前到达第 $i$ 行,且有 $j$ 列放置两个炮、$k$ 列放置一个炮。那么相应的放置 $0$ 个炮的列数就是 $m-j-k$。
01-trie 是一种特殊的 trie 树,是将整数作为二进制形式插入到 trie 中形成的字典树,其字符集为 $\{\mathtt0,\mathtt1\}$。01-trie 能够高效地维护许多关于异或的问题。
给定一个长度为 $n$ 的数组 $a_1,a_2,\dots,a_n$,你需要求出最大的异或对,即 $(i,j)$ 使得 $i\neq j$,$a_i\oplus a_j$ 最大。
贪心的想,如果我们知道了所有数的二进制表示,当想求最大的 $a_i\oplus x$ 时,我们只需要让 $x$ 的高位与 $a_i$ 对应的位尽量不同就可以了。(一个高位可以抵得上剩下的所有低位。)
因此我们枚举 $i$,并将 $a_1,a_2,\dots,a_{i-1}$ 全部从高位到低位地插入到 01-trie 中。接下来我们在 trie 中查找答案,从根节点向下跳,如果能走到与 $a_i$ 当前位不同的方向就一定走,否则只能走另一侧。最后走下来的路径异或上 $a_i$ 就是对于 $a_1,a_2,\dots,a_i$ 的最大异或对。