E. 玩游戏
运行时间限制: 1000 | 运行内存限制: 65536 |
作者: scsyuanbaoku | 是否specialjudge: False |
题目描述
你正在玩一款新的游戏,在游戏中你有N个用于给你的战士补充能量的道具和M个战士。这N个道具都有一个能量值,代表该道具能给战士提供的总能量,给战士补充后该值会永久减少,该值为0后该道具就没有用了。例如某道具的能量值为500,如果用它给一个战士补充了300的能量,则该道具的能量值变为200。现在你要带领你的战士们出征了,在出征前你要给这M个战士补充能量。假设初始时每个战士的能量都为0,补充完后所有的战士的能量都一样。如果一个战士在补充能量时只能使用1个道具(1个道具可以给若干个战士补充能量)。现在请你写一段程序来计算一下,你最大能给每个战士补充的能量值是多少?
输入:
第一行为2个整数,分别代表N(1<=N<=10000)和M(1<=M<=20000)
第二行为N个整数,代表这N个道具能提供的能量值(所有能量值大于等于100且小于等于2000000)。
输出:
为一个整数,代表你最大能给每个战士补充的能量值。测试数据保证有解。
输入样例
5 13
765 506 483 329 492
输出样例
164
解法:
我们可以反转思路,假设我给定一个值x,那么是不是能是每个战士的能量都到达这个值呢?用ai表示第i个能量块的能量,如果sum(floor(ai/x))>=n ,1<=i<=m(sum表示求和,floor表示向下取整),就说明可以,如果<n则不行floor(ai/x)是求出这个能量块能给几个战士补充能量。
然后我们发现答案还有一个性质就是加入x可行,那么如果y<x,x一定也可行;假如x不可行,那么如果y>x,y也一定不可行。所以我们想到答案一定是在某一个点发生了突变,x可行,x+1不可行、
此时的x也就是答案了。
所以此时采用二分的方法,设一个l,一个r
满足l<=ans,r>ans
此时我们计算出mid=(l+r)/2
如果mid可行那么l=mid;
如果不可行,那么r=mid;
知道l=ans,r=ans+1
(判断条件为r-l==1)
#include<stdio.h> #include<stdlib.h> int a[10005],m,n,mx; bool f(int z){ int s=0; for(int i=1;i<=n;++i) s+=a[i]/z; return m<=s; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); if(a[i]>mx) mx=a[i]; } int l=0,r=mx+1; while(l<r-1){ int mid=(l+r)/2; if(f(mid)) l=mid; else r=mid; } printf("%d",l); system("pause"); return 0; }