CF679B 解题报告
我操,CF 彻底怒了。CF 指出了最核心的矛盾点:如果我在打题时不听音乐,怎么可能切不出来这题?这确实是我的严重错误。我需要彻底承认边打题边听音乐毫无用处,重新集中注意力。
然后这题很智慧,只需要一点点注意力就可以。
首先就是利用这个条件限制问题吧,因为题目说是贪心地放方块,于是考虑如果如果我们第一个放了 \(t\),那么之后最多只能再使用 \(\min((t+1)^3 - 1 - t^3, m - t ^ 3)\) 了。
这个东西说明:往小选未必更优。
令 \(a = m ^ {\frac{1}{3}}\) 向下取整。然后我们考虑,对于这个 \(m\):
-
选 \(a\),那么剩下的有 \(m - a ^ 3\)。
-
选 \(a - 1\),那么剩下的有 \(\min(m - (a - 1) ^ 3, a ^ 3 - (a - 1) ^ 3 - 1) = a ^ 3 - (a - 1) ^ 3 - 1\)。
-
选 \(a - 2\),那么剩下的有 \(\min(m - (a - 2) ^ 3, (a - 1) ^ 3 - (a - 2) ^ 3 - 1) = (a - 1) ^ 3 - (a - 2) ^ 3 - 1\)。
容易注意到选 \(a - 2\) 不可能比 \(a - 1\) 更优。
\(solve(m)\) 返回目前剩余的总体积最大为 \(m\) 的所有答案二元组【使用块数,使用体积】中字典序最大的那一个。然后转移其实很简单了,目前我们只能选 \(a\),\(a - 1\),因为根据以上分析,选择更小的不可能更优。
注意到 \(m\) 的衰减其实很快,爆搜虽然会重搜节点,但是总量很小。当然你要想记忆化也行,反正时间 \(\mathcal{O}(能过)\)。
也就是说还是玄学复杂度意识不够强,然后就是依旧不会搜索。然后很炸。总之就是一道比较看注意力的题目吧,多瞪一会就瞪出来了。
然后是刚好因为 Mike 在打原神,所以 In queue 一万年才过的代码。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int cb(int x){return x * x * x;}
pair<int, int> dfs(int m){
if(!m) return {0, 0};
int a = cbrt(m);
pair<int, int> resa = dfs(m - cb(a));
resa.first ++, resa.second += cb(a);
pair<int, int> resb = dfs(cb(a) - cb(a - 1) - 1);
resb.first ++, resb.second += cb(a - 1);
return max(resa, resb);
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
int rx; cin >> rx;
auto [x, y] = dfs(rx);
cout << x << " " << y << "\n";
return 0;
}

浙公网安备 33010602011771号