题目(塔):
【题目描述】
小A想搭一个体积不超过m的塔,他有各种大小的立方积木,比如边长为a的积木,体积为a^3,现在小A需要你给一个X,每次小A会用一个体积不超过X的最大积木,依次到搭好为止,现在他想最大化积木的个数,同时在积木个数最大的情况下使X最大
【输入】
一行一个数m
【输出】
一行两个数,最多积木数以及x
【样例输入】
48
【样例输出】
9
42
【样例解释】
X=23或42都是9次,42 = 3^3 + 2^3 + 7*1^3
【数据范围】
30%:m<=10^5
50%:m<=10^10
100%:m<=10^15
分析:
设f(m)表示在体积不超过m的情况下最大的积木个数
找到a使得a的立方为小于m且与m最接近的数
则:下一块积木一定为a或a-1
证明:1.用 a,则m更新为m-a^3
2.用 a-1, X最大为 a^3-1, m更新为 a^3-1-(a-1)^3=a^2-a
3.用 a-2, X最大为(a-1)^3-1,m更新为(a-1)^3-1-(a-2)^3=a^2-3a+6
在a>=3的情况下法2比法3更优
所以只需考虑前2种情况。
代码:
#include<bits/stdc++.h>
using namespace std;
long long d[100100],m,ans,ret=0,retx=0,t;
long long lifang(long long x){
return x*x*x;
}
void rec(long long m,long long cnt,long long s){
if(m==0){
if(cnt>ret||(cnt==ret&&s>retx)){
ret=cnt;
retx=s;
}
return ;
}
long long x=1;
while(lifang(x+1)<=m) x++;
rec(m-lifang(x),cnt+1,s+lifang(x));
if(x>=1) rec(lifang(x)-1-lifang(x-1),cnt+1,s+lifang(x-1));
return ;
}//递推
int main(){
cin>>m;
rec(m,0,0);
cout<<ret<<" "<<retx;
return 0;
}