Bear and Tower of Cubes Codeforces - 680D
https://codeforces.com/contest/680/problem/D
一道2D,又是搞两个小时才搞出来。。。不过好在搞出来了
官方题解:可以证明对于m,设a是满足a^3<=m的最大a,那么选a或a-1一定最优;那么可以暴力dfs
....23333.。。。。。
完了,我也不知道为什么这个代码能A了
我的想法(仅做记录):对于m=m1的方案,如果最大的选a,那么说明X在[a^3,min((a+1)^3-1,m1)]区间内;这个区间的两个端点都减去a^3后,就发现m=m1的方案,相当于在m=min((a+1)^3-1,m1)-a^3时的方案上再补上取一个a
然后我打了一个很naive的暴力,就是枚举最大的数(设为i)。。根本不能A
考虑优化这个dp:
当m1<(i+1)^3-1即i>(m+1)的三次方根-1时,答案是m=m1-i^3时的答案补上取一个i,显然i变得更小时,答案的第一项不会变得更差,但是当答案的第一项相等时,i越大答案的第二项越好,因此暴力从最小的可能i枚举到最大的可能i,更新答案,如果发现枚举到某处时这一次得到的答案比当前总答案第一项劣,就跳出(所以其实是玄学暴力23333)
当m1>=(i+1)^3-1即i<=(m+1)的三次方根-1时,答案是m=(i+1)^3-i^3-1的答案补上取一个i,显然i变得更大时,答案总体不会变得更劣,因此只求i=(m+1)的三次方根-1时的答案即可
看了题解后发现自己这样搞其实有些无用的枚举(就比如第一种情况也是只考虑一个值就行了,这就是65行以后漏掉了对lt的赋值还能A的原因)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<map> 6 #include<cmath> 7 using namespace std; 8 #define fi first 9 #define se second 10 #define mp make_pair 11 #define pb push_back 12 typedef long long ll; 13 typedef unsigned long long ull; 14 typedef pair<ll,ll> pll; 15 const ll N=100000; 16 ll poww(ll x) 17 { 18 return x*x*x; 19 } 20 ll work(ll x) 21 { 22 ll t=pow(x,0.333333333333333333); 23 while(poww(t+1)<=x) t++; 24 while(poww(t)>x) t--; 25 return t; 26 } 27 map<ll,pll> an;ll num; 28 //pll solve(ll m) 29 //{ 30 // if(an.count(m)) return an[m]; 31 // //num++; 32 // //if(num%100000==0) printf("%lld\n",num); 33 // //printf("%lld\n",m); 34 // //scanf("%d",new int); 35 // pll ans,t;ll tt; 36 // for(ll i=1;i<=N;i++) 37 // { 38 // tt=poww(i); 39 // if(tt>m) break; 40 // //if(poww(i+1)-1>m) break; 41 // t=solve(min(m,poww(i+1)-1)-tt); 42 // t.fi++;t.se+=tt; 43 // ans=max(ans,t); 44 // } 45 // return an[m]=ans; 46 //} 47 pll solve(ll m) 48 { 49 if(an.count(m)) return an[m]; 50 pll ans(-233,-233),t,lt(-1,-1);ll t3=work(m+1)-1; 51 if(t3>0&&t3<=N) 52 { 53 t=solve(poww(t3+1)-poww(t3)-1); 54 t.fi++;t.se+=poww(t3); 55 ans=t; 56 } 57 if(t3!=m) 58 { 59 for(ll i=t3+1;i<=N;i++) 60 { 61 if(m-poww(i)<0) break; 62 t=solve(m-poww(i)); 63 if(lt.fi!=-1&<.fi!=t.fi) break; 64 t.fi++;t.se+=poww(i); 65 ans=max(ans,t); 66 } 67 } 68 return an[m]=ans; 69 70 } 71 72 int main() 73 { 74 ll m; 75 an[0]=mp(0,0); 76 scanf("%lld",&m); 77 auto t=solve(m); 78 printf("%lld %lld\n",t.fi,t.se); 79 return 0; 80 }