1. 程式人生 > >2018.09.24 塔(搜尋)

2018.09.24 塔(搜尋)

描述

小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

一道簡單搜尋。 每次遞迴的時候找到最大的 a 使得 a^3 不超過 m。 那麼這時接下來X的第一塊積木的邊長可以在1~a之間。 但是可以證明接下來 X 的第一塊積木必然為 a或 a-1。 因為選長度為a

2a-2的不如選a1a-1的優秀。 每次 遞迴的時候m 都會變成m^(2/3)。 這樣搜一搜就行了。 程式碼:

#include<bits/stdc++.h>
#define ll long long
#define xx first
#define yy second
using namespace std;
pair<ll,ll>ans;
ll m,maxn,pos;
inline ll calc(ll x){return x*x*x;}
inline void solve(ll tot,ll tim,ll sum){
	if(!tot){ans=max(ans,make_pair(tim,sum));return;}
	ll tmp=1;
	while(calc(tmp+1)<=tot)++tmp;
	solve(tot-calc(tmp),tim+1,sum+calc(tmp)),solve(calc(tmp)-calc(tmp-1)-1,tim+1,sum+calc(tmp-1));
}
int main(){
	maxn=0,pos=0;
	scanf("%lld",&m);
	solve(m,0,0);
	printf("%lld %lld",ans.xx,ans.yy);
	return 0;
}