【递推】【2018.9.22提高组模拟】T2(WOJ 3977) 塔

题目():

【题目描述】  

小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;
} 

猜你喜欢

转载自blog.csdn.net/qq_42754826/article/details/82813604