题意
在[1,m]中选出x,使得x能按下列规则变换尽量多次,在满足尽量多次的前提下求最大的x。
1. 若x>=1,则设a为小于等于x的最大完全立方数,x=x-a,重复步骤1
2. 若x=0,退出。
分析
我们设一个双值函数 f(m) 表示x取[1,m]时的最大次数与最大x。
设a为小于等于x的最大完全立方数.
我们希望将f分解为若干小问题(分治)。
假设当前这个放a的话,那么我们就有一个新的m取值范围
m2=m−a3
。
假设当前这个放a-1的话,那么我们就有一个新的m取值范围 m2=a3−1−(a−1)3 ,因为x即使在[1,m]的范围下,最多也只能取到 a3−1 ,不然就要用 a3 了。
假设当前这个放a-1的话,那么我们就有一个新的m取值范围 m2=(a−1)3−1−(a−2)3 ,显然比放a-1要小。
因为2与3对次数的贡献是一样的,所以自然是m2越大越好。因为 f(x)优于f(x−1)
所以每次只需要取1,2者尝试。时间复杂度
T(m)=T(m−a3)+T(a3−(a−1)3−1)
暂时不会分析。
#include <cstdio>
#include <iostream>
#include <cmath>
typedef long long ll;
using namespace std;
ll m,a,b;
const double f3=(1/(double)3);
void solve(ll x,ll &cnt,ll &X) {
if (x==1) {cnt=1,X=1; return;}
if (x==0) {cnt=0,X=0; return;}
ll mx=pow(x,f3);
ll a1,a2,b1,b2;
solve(x-mx*mx*mx,a1,b1);
solve(mx*mx*mx-1-(mx-1)*(mx-1)*(mx-1),a2,b2);
cnt=max(a1,a2)+1;
if (a1>=a2) X=b1+mx*mx*mx; else X=b2+(mx-1)*(mx-1)*(mx-1);
}
int main() {
freopen("2.in","r",stdin);
cin>>m;
solve(m,a,b);
cout<<a<<" "<<b<<endl;
}