「JOI 2018 Final」毒蛇越狱
「JOI 2018 Final」毒蛇越狱
Algorithm 1: 暴力计算
对于所有 \(0,1,?\) 组成的 \(3^n\) 种串处理出答案
具体的,对于当前串包含的最后一个 \(?\) 位置,枚举它变成0/1的答案,按照一定的顺序累和即可
(代码可以在Algo2里面看到)
Algorithm 2 : Meet in the Middle
\(3^{20}\) 太大,优化上面的暴力,容易想到把复杂度从预处理分一部分给查询
取出 \(n\) 中前 \(k\) 个位置,这些位置不处理 \(3^k\) ,而是让每个询问暴力地去枚举这些位置上的 \(?\) 变成 \(0/1\)
显然每个询问有最多 \(2^k\) 次枚举,即复杂度为 \(O(Q\cdot 2^k)\)
对于剩下的 \(n-k\) 个位置,采取上面的暴力方法预处理,三进制枚举,预处理复杂度为 \(O(2^k3^{n-k})\)
因此复杂度为 \(O(Q\cdot 2^k +2^k3^{n-k})\) ,计算在 \(k=6,7\) 时复杂度约为 \(3.5\cdot 10^8\)
(这是一个非常稳的复杂度)
1 |
|
Algorithm 3 : 高位前缀和+容斥
起始学过高位前缀和/FMT的看到这个题第一反应可能都是这个。。
-> 对于 \(?\) 的位置,直接赋值成1,然后对于这个数从高位前缀和里查询
然后你发现不知道怎么对于1的把0的去掉
显然这个可以通过一个暴力的容斥来完成,枚举一些1的位置变成0,然后就是容斥的奇数减偶数加
复杂度为 \(O(Q\cdot 2^{1的个数}\ \ \ \ \ )\)
同理,处理高位后缀和,复杂度为 \(\begin{aligned}O(Q\cdot 2^{0的个数}\ \ \ \ )\end{aligned}\)
而直接暴力枚举 \(?\) 变成0/1,复杂度为 \(\begin{aligned}O(Q\cdot 2^{?的个数}\ \ \ \ \ )\end{aligned}\)
综合这三种算法,选一个更优的做,就得到一个复杂度为
\(\begin{aligned}O(Q \ \cdot 2^{ \begin{aligned}\ \ \ \ \ \ \ \ \ \ \min\lbrace 1的个数,0的个数,?的个数\rbrace\end{aligned}})\ \ \ \ \ \ \end{aligned}\)
显然查询复杂度就是 \(O(Q\cdot 2^{\lfloor \frac{n}{3}\rfloor }=Q\cdot 2^6)\)
算上预处理,复杂度为 \(O(2^nn+Q\cdot 2^6)\)
1 |
|