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&&lt.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 }

 

posted @ 2018-07-29 21:59  hehe_54321  阅读(189)  评论(0编辑  收藏  举报
AmazingCounters.com