题解 CF913C 【Party Lemonade】

囧仙

2020-05-13 21:27:18

Solution

## 题目大意 $n$种柠檬汁,每种体积为$2^{i-1}$,价格为$W_i$。询问购买总体积不小于$L$的柠檬汁,最少要花多少钱。 ## 题解 很显然,如果$2\times W_i<W_{i+1}$,那么我们就可以用两瓶$i$种柠檬汁来替代一瓶$i+1$种柠檬汁。这样可以保证,一次购买的体积越大,平均花费的钱越少。 让我们从一个简单的问题入手:假如你有$m$元,你**最多**能够购买到多少柠檬汁呢? 根据上述的贪心方法,我们能够发现,**尽可能购买体积更大的柠檬汁能省更多钱**。他的正确性比较容易说明。很显然,如果我们需要购买两次$i$种柠檬汁,就不如购买一次$i+1$种柠檬汁,因此每种果汁**最多购买一瓶**。如果我们放弃购买第$i$种柠檬汁,即使我们将剩下的种类都买了一遍,也达不到它的体积,甚至还要花费更多的钱。 因此,这样一个二分的算法就出来了。每次判断$x$元能否购买到$L$体积的柠檬汁,进行二分操作即可。 ## 参考代码 ```cpp #include<bits/stdc++.h> #define up(l,r,i) for(int i=l;i<=r;i++) #define dn(l,r,i) for(int i=l;i>=r;i--) using namespace std; typedef long long LL; const int INF =2147483647; LL qread(){ LL w=1,c,ret; while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0'; while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0'; return ret*w; } LL n,l,W[31],ans,p,k; bool chk(LL x){ LL ret=0; dn(30,0,i) if(x>=W[i]) ret+=(1<<i),x-=W[i]; return ret>=l; } int main(){ n=qread(),l=qread(); W[0]=qread(); up(1,n-1,i){ W[i]=qread(); if(W[i]>W[i-1]<<1) W[i]=W[i-1]<<1; } up(n,30,i) W[i]=W[i-1]<<1; p=0,k=1; while(k){ if(!chk(p+k)) p+=k,k<<=1; else k>>=1; } printf("%lld\n",p+1); return 0; } ```