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;
}