CF2131G 题解
调了一个下午,发现 long long 存不下 \(2^{63}\)。
我们考虑如何删掉一个数。以 \(4\) 举例:
状压一下(第 \(i\) 位是 \(1\) 当且仅当 \(i + 1 \in S\)):
于是需要 \(8\) 步,得分会乘 \(\prod \limits_{i = 1}^8 (\log_2(\operatorname{lowbit}(i)) + 1)\)。总结出规律:想删掉 \(n\),需要 \(2^{n - 1}\) 步,得分会乘 \(\prod \limits_{i = 1}^{2^{n - 1}} (\log_2(\operatorname{lowbit}(i)) + 1)\)。
考虑如何快速计算 \(f(n) = \prod \limits_{i = 1}^n (\log_2(\operatorname{lowbit}(i)) + 1)\)。把 \(\log_2(\operatorname{lowbit}(i)) + 1\) 写出来:\(1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, \cdots\),发现这个数列的第 \([1, 2^i - 1]\) 项一定对称,于是考虑分治。
-
若 \(n = 2^m - 1\):\(f(n) = m \cdot f^2 \left( 2^{m - 1} - 1 \right) = \lceil \log_2(n) \rceil \cdot f^2 \left( \left \lfloor \dfrac{n}{2} \right \rfloor \right)\)。
-
否则:设 \(n = 2^a + b\),其中 \(b < 2^a\),则 \(f(n) = f ( 2^a - 1 ) \cdot (a + 1) \cdot f(b)\)。
Q. 如何求 \(2^a\)?
A. \(2^a\) 实际上就是 \(n\) 的最高位。
i64 highbit(i64 x) { x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x |= x >> 32; return x - (x >> 1); }
回到题目,我们首先把 \(s\) 排序,然后从小到大删。
如果剩余步数足够删完 \(s_i\),那就把答案乘上 \(f(2^{s_i - 1})\)。
如果不够,设还剩 \(k'\) 步,\(x = 2^{s_i - 1}\),则要把答案乘上 \(\prod \limits_{i = x - k' + 1}^x (\log_2(\operatorname{lowbit}(i)) + 1)\)。根据这个数列的对称性,我们可以把这个式子变成 \(s_i \prod \limits_{i = 1}^{k' - 1} (\log_2(\operatorname{lowbit}(i)) + 1) = s_i \cdot f(k' - 1)\)。
时间复杂度:\(O(n \log V)\),其中 \(V\) 为值域。代码。

浙公网安备 33010602011771号