其实是 duel 记录,但是不知道为啥想起名为《十重塔》,可能是叠谜做魔怔了。
难度 \([2600,2700]\)。
目前战绩 wsc 11:10 grg,但是 grg 显然比我牛。
- CF201E,wsc 胜,1:0
问题等价于,一个 \(n\) 行 \(k\) 列的 \(01\) 矩阵,每行有不超过 \(m\) 个 \(1\),使得每一列组成的二进制数不同,求 \(k\) 的最小值。
考虑二分 \(k\),现在判断 \(k\) 列能区分的行数是否 \(\ge n\)。我们观察到,每行 \(1\) 个数不超过 \(m\) 等价于所有的 \(1\) 个数不超过 \(mk\)(做的时候没证明)。
证明:假设当前状态总个数不超过 \(mk\) 且有一行超过 \(m\) 个,那么取出这一行,设为行 \(x\),再找出一行个数 \(<m\)(显然一定存在),设为行 \(y\),考虑将某一位上 \(x,y\) 调换,其中 \(x\) 是 \(1\),\(y\) 是 \(0\),且交换后维持二进制数两两不变。不难发现满足 \(x=1,y=0\) 的数一定比 \(x=0,y=1\) 的数多(具体可以考虑去掉 \(x=0,y=0\) 和 \(x=1,y=1\) 的数,此时 \(x,y\) 的 \(1\) 数量差不变,那么 \(x=1\) 比 \(y=1\) 多),因此可以交换使得 \(\sum\limits _{i=1}^{n} \max (m-c_i,0)\) 变小,一定在有限次操作后结束。
那么考虑贪心,按照 popcount 一次从小到大填,每次可以放的个数是二项式系数,预处理较小一部分,暴力乘法算大的部分。复杂度 \(\mathcal O(\log ^2n)\)。
- CF1091F,grg 胜,1:1
这题是真没想到,服输。
考虑反悔贪心,每一段优先飞,用堆维护前面飞过的所有路程可以累计能量的方式。每次飞了能量不够了就从堆中依次用代价最小的补充。补充有两种方式,第一种是把飞的变成走的,第二种是来回走。
- CF566B,grg 胜,1:2
这个题我先想出做法的,但是 grg 的乱搞误打误撞对了,写的比我快,把我爆了。
发现每次找任意一个能做的操作做就是对了。证明略。
因此拿个 set 或者啥维护即可。