官方:Let’s find the maximum a that a3 ≤ m. Then, it’s optimal to choose X that the first block will have side a or a - 1. Let’s see why
if the first block has side a then we are left with m2 = m - first_block = m - a3.
If the first block has side a - 1 then the initial X must be at most a3 - 1 (because otherwise we would take a block with side a), so we are left with m2 = a3 - 1 - first_block = a3 - 1 - (a - 1)3
If the first blocks has side a - 2 then the initial X must be at most (a - 1)3 - 1, so we are left with m2 = (a - 1)3 - 1 - first_block = (a - 1)3 - 1 - (a - 2)3.
We want to first maximize the number of blocks we can get with new limit m2. Secondarily, we want to have the biggest initial X. You can analyze the described above cases and see that the first block with side (a - 2)3 must be a worse choice than (a - 1)3.
It’s because we start with smaller X and we are left with smaller m2. The situation for even smaller side of the first block would be even worse.
Now, you can notice that the answer will be small. From m of magnitude a3 after one block we get m2 of magnitude a2. So, from m we Go to m2 / 3, which means that the answer is O(loglog(m)). The exact maximum answer turns out to be 18.
The intended solution is to use the recursion and brutally check both cases: taking a3 and taking (a - 1)3 where a is maximum that a3 ≤ m. It’s so fast that you can even find a in O(m1 / 3), increasing a by one.
# include <iostream> # include <cstdio> # include <algorithm> # define LL long long using namespace std; LL a[100010]; pair<LL, LL>ans; void DFS(LL now, LL cnt, LL sum) { if(!now) { ans = max(ans, make_pair(cnt, sum)); return; } int pos = upper_bound(a+1, a+100002, now) - a; --pos; DFS(now - a[pos], cnt+1, sum+a[pos]); if(pos >1) DFS(a[pos]-a[pos-1]-1, cnt+1, sum+a[pos-1]); } int main() { LL p; scanf("%I64d",&p); for(LL i=1; i<=100002; ++i) a[i] = i*i*i; DFS(p, 0, 0); printf("%I64d %I64d\n",ans.first, ans.second); return 0; }