Codeforces 913C Party Lemonade

9 篇文章 0 订阅
8 篇文章 0 订阅

题目在这里呀!

像我这么傻的人怎么能做这种毒瘤贪心题呢?

一道题够想一整天我也真的是弱的。


题意:有n种柠檬汽水,第i种柠檬汽水的容积为2^(i-1),花费为ci,可以取无限次。

问使总容积至少为L的最小花费。


题解:怎么也觉得这道题有毒,可全世界都做出了这道题啊...

有一点是肯定的,如果第i-1种汽水买两瓶比买第i种汽水的花费要少的话,那么就用少的那个。

这样就首先更新了c[i]数组。

然而这题的汽水容积很特别都是2的指数次幂,所以可以利用。


显然c[i]每一步都是更优的,即如果能取容积指数大的汽水那一定取它更优,所以就考虑先取到不能取为止,然后再递归向下取。

还需要注意一些问题。

如果你当前先取了一个i然后递归向下找,你也可以再取一个i来代替它,因为后面所有的都取的容积都不会超过i的容积。

再想一想,其实不一定需要取i,我们设对于取完一个i之后剩余的容积比它大的最小的容积为2^j,那么我们可以在j到i所有的c[i]任取一个就行了。


所以这道题嘛就差不多做完了,最后还要注意,一开始就取容量超过L的也是可行的,所以还要取个min。


然后就把这道毒瘤题讲完啦!

以后再也再也不做贪心题了qwq




#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
int n,L,k;ll ans,c[34];

inline ll dfs(int x){
    int pos=34;
    for(int i=0;i<=30;i++) if(x < (1<<i)) {pos=i-1;break;}
    if(x==(1<<pos)) return c[pos];
    ll rest=x-(1<<pos);
    ll sum=dfs(rest);
    int pos1=34;
    for(int i=0;i<=30;i++) if(rest < (1<<i)) {pos1=i-1;break;}
    for(int i=pos1+1;i<=pos;i++) sum=min(sum,c[i]);
    return c[pos]+sum;
}

int main()
{
    scanf("%d%d",&n,&L);
    for(int i=0;i<n;i++) scanf("%lld",&c[i]);
    for(int i=1;i<n;i++) c[i]=min(c[i],c[i-1]+c[i-1]);
    for(int i=n;i<=30;i++) c[i]=c[i-1]+c[i-1];
    k=34;
    for(int i=0;i<=30;i++) if(L < (1<<i)) {k=i;break;}
    ans=dfs(L);
    for(int i=k;i<=30;i++) ans=min(ans,c[i]);
    printf("%lld\n",ans);
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值