ARC 184 ABD
A
感谢某人以高水平获得了 8 发罚时。
显然分组。考虑 11 个分为一组,这样一个组里面就不可能全是假币。然后对于每一组,让其中第一个元素去问另外 10 个元素。花费次数:\((1000/11)*10=910\) 次。(注意最后一组只有 10 个,要特殊处理)
如果一个组里面回答都是 0 的话,肯定就都是真币了,直接不管。考虑有 1 的情况,那么一定有假币。
发现很暴力啊,你先把组内第一个元素和外面随便一个是真的元素问 1 次(之前那些全是真币的组任选一个),就可以得到这个元素是真是假,再根据之前的组内询问就可以直接推出组内所有币的真假。
考虑最后 1 组,可能全部返回 0 但全部是假币,这个可以当其它组都是真币时直接推出,其余情况还是一样的。
所以一共只需要问 \(919\) 次(后面问 9 次就知道最后一个的情况了),当然还可以优化到 909。
B
第一道轮廓线 dp。
前置知识:集合选数。
我们考虑以每个 \(i\) 作为矩阵的第一项,构造出一个 \(\log_2 n\times \log_3\) 的矩阵。显然不同的 \(i\) 形成的矩阵都是独立的,即里面没有重复元素。
对一个矩阵单独考虑,我们对每一行状压,由于列数是 \(\log_3 n\),所以状压过后是 \(n^{2/3}\),可以接受。
发现普通的状压无法转移,所以我们需要轮廓线,题目的操作在矩阵中就是操作点 \((x,y)\) 使得点 \((x,y),(x+1,y),(x,y+1)\) 都被选中。
方程式很简单,最后返回选完所有数的答案即可。
然而还要优化,因为这种矩阵太多了。发现这个矩阵的大小是由 \(n/x\) 下取整决定的,如果这个值一样那么所有 \(x\) 所构造出来的矩阵大小都是一样的,只计算一次即可,这类似于整除分块。
时间复杂度我不会算,以及我实现较劣,时限 8s 我跑了 7.8s。
D
为什么场上会一直想区间 dp 呢。
这题的难点在于如何避免算重,我们需要加强对状态的限制。
考虑 dp 操作序列(显然顺序不影响,所以按 x 升序进行 dp),令 \(dp_i\) 表示对 \(i\) 进行操作,并枚举上一个操作的位置 \(j(j<i)\) 转移过来。
如何避免不会算重?这里我们再限制:对于当前的操作序列,如果再操作任意一个球都会改变剩下的球。非常妙,使我想不到。
这样设计过后,所有剩下球的状态都会对应唯一的 dp 状态中的操作序列(尽管 dp 中某次操作没有改变剩下的球),两者形成双射。
然后就是转移条件了:(\(j<i\),把下标当成 x 轴)
-
保证每个球都可以被操作,不存在操作一次球之后把其他待操作的球弄没了的情况:\(a_j>a_i\)。这里的结论是操作序列按下标排序后 \(y\) 值是单减的。
-
由于 \((j,i)\) 内的球都没有操作,所以根据定义的限制,要判断是否所有的 \(k(j<k<i)\),它操作过后都会改变剩下的球。当然为了保证 \(k\) 可以操作,还要 \(k\) 满足 \(a_j>a_k>a_i\)。
状态线性,枚举转移点线性,判断是否可以转移线性,时间复杂度为 \(O(n^3)\)。当然这东西显然可以大大优化,不讨论。
代码:
A:https://atcoder.jp/contests/arc184/submissions/58077662