1. 程式人生 > >【2018/09/23】T2

【2018/09/23】T2

塔(30/100)

描述

小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

【分析】

這個題目描述依舊很鬼畜……大部分同學又沒有讀懂了(主要是題意沒有敘述清楚)

重述:

給定m,請你確定[ 1 , m ]中的 x ,使得用到的積木數最多,每次取積木的原則:取當前可取的最大的那一個。在滿足積木數最大的情況下,輸出最大的 x 

這下應該清楚一些了吧。

首先30分的暴力:列舉 x (1~m) ,然後挨個判斷

50分:dp

100分:在50 分的dp上進行優化

找到最大的 a 使得 a^3 不超過 m,接下來 X 的第一塊積木必然為 a 或 a-1  1.用 a,m2=m-a^3  2.用 a-1, X最大為 a^3-1, m2 = a^3-1-(a-1)^3=3*(a^2-a)  3.用 a-2, X最大為(a-1)^3-1,m2 ’ =(a-1)^3-1-(a-2)^3=3*a^2-9a+6  顯然2一定比3優 

【程式碼】

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll m;
pair<ll,ll> ans;
ll val[1000009],num=0;
void search(ll x,ll steps,ll ss){
	if(x==0){
		ans=max(ans,make_pair(steps,ss));
		return ;
	}
	ll a=lower_bound(val+1,val+100001,x)-val;
	if(val[a]>x) a--;
	search(x-val[a],steps+1,ss+val[a]);
	if(a-1>=0) search(val[a]-1-val[a-1],steps+1,ss+val[a-1]);
}
int main(){
	scanf("%lld",&m);
	for(int i=1;i<=100000;++i)	val[i]=1ll*i*i*i;
	search(m,0,0);
	printf("%lld %lld",ans.first,ans.second);
	return 0;
}