二分第二弹



description
 
我们都知道,ACM比赛的排名认定是解题数目,和解题所需的总时间。现在,你们正在准备打一场比赛,已知题目总数n和每道题的难度a[i],(1 <=a[i]<=1e7).假设你的解题能力是x,(1 <=x <= 1e7),从而你解出一道题所需的时间是ceil(a[i]/x)。你给自己定的目标是在t时间内至少做出k道题,那么问题来了,你在比赛正式开始之前只要要修炼到多少能力值才能达成目标?
ps:ceil()表示向上取整


 


input 


输入多组数据,每组数据第一行是一个整数n,(n < 1000),表示比赛的题目总数,接下来一行是n个整数,表示每道题的难度值。再接下来一行输入一个整数q,(q < 100),表示这组数据里要进行的q次询问。每次询问输入两个整数,t和k,意义如上所述,占一行。(t <= 1e7, k <= n)


 


output 


对每组数据的每次询问,输出你所需的解题能力值x(x也是整数= =),占一行。


 


sample_input 


5
2 4 8 16 32
5
5 4
5 3
10 3
20 5
30 4




 


sample_output 


8
4
2
4
1




 


hint 


解出每道题所需的时间都是整数。


此题的二分还是比较有难度的,当初写这题硬是花费了一下午的时间,不过主要还是得读懂题目意思,不然自己带中间三组数据带到样例里面怎么看也都是错的。所以这题关键在于理解题目,并非样例的数字都是恰好准确,而是要求至少,至少满足了就行,所以以后读题还得仔细理解啦~~下面附上自己一下午的心血:
#include <iostream>
#include<stdio.h>
#include<algorithm>


using namespace std;
int ceil(int a,int b)
{
    double s=1.0*a/b;
    if((int)s-s!=0)
        return (int)s+1;
    else return (int)s;
}


int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int a[1000];
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        int q,t,k;
        scanf("%d",&q);
        for(int i=0;i<q;i++)
        {
            scanf("%d%d",&t,&k);
            int low=1,high=10000000,mid,s=0,x=0,b[100];
            while(low<=high)
            {
                s=0;
                mid=(low+high)/2;
                for(int j=0;j<k;j++)
                    s+=ceil(a[j],mid);
                if(s<=t)
                {
                    b[x]=mid;
                    high=mid-1;
                    x++;
                }
                else if(s>t)
                    low=mid+1;
            }
            printf("%d\n",b[x-1]);
        }
    }
    return 0;
}
posted @ 2015-02-09 22:09  martinue  阅读(122)  评论(0编辑  收藏  举报