2017年“华信智原杯”安徽省大学生程序设计大赛C题-刷票

C. 刷票

题目描述:
有一个选秀比赛,节目组按照观众的投票情况决定选手的去留。为了给旗下 艺人造势,A 公司收买了一批水军来刷票。已知现在有 n 名选手同台竞争,依次 编号 1…n,A 公司的艺人编号为 1。根据节目组的规定,每人只能投票一次,投 票需要在 n 个选手中选出 m 个,这 m 个人每人可以获得一票。A 公司通过秘密 渠道得知了在 A 公司的水军不参与的情况下最终的投票结果,那么 A 公司想要 知道,如果要让公司旗下的艺人获得第一名(不能并列),至少要出动多少名水 军呢?如果无解,输出"Impossible"(不含引号)

输入描述:
第一行输入正整数 T,表示数据的组数。 对于每组数据,第一行为两个正整数 n, m(1<=m<=n<=100000)。 第二行行为 n 个空格隔开的整数。表示第 i 个选手的得票数,且有 1… |1 100000 ii n a    

输出描述:
对于每组数据,输出一行,格式为’Case t: x’,t 为数据的组号,x 为题目要求 的结果。

输入样例:
2

3 2

2 3 3

4 2

1 2 3 4

输出样例:
Case 1: 4

Case 2: 5

样例解释:
对于第一组数据,投票过程如下:

2 3 3 => 3 4 3 => 4 5 3 => 5 5 4 => 6 5 5 

因此至少需要 4 名水军
#include<stdio.h> 
#include<cmath> 
int main()  
{  
    int k = 1, t ;  
    scanf("%d",&t);  
    while(k++<=t)  
    {  
        int n, m;  
        scanf("%d %d",&n,&m);  
          
        int ticket[100005];  
        for(int i = 1;i<=n;i++)  
            scanf("%d",ticket+i);  
              
        int j = 1, max = ticket[1];  
        for(int i = 2;i<=n;i++)      //判断是否有别的值比ticket[1]大,并找出来   
            if(ticket[i]>=max)         
            {  
                j = i;  
                max = ticket[i];  
            }   
              
        if(j==1)                    //ticket[1]就是最大的   
        {  
            printf("Case %d: 0\n",k-1);  
            continue;  
        }  
          
        if(n==m)                    //n==m且ticket[1] 不是最大的,则无解   
        {  
            printf("Case %d: Impossible\n",k-1);  
            continue;  
        }  
          
        int a = max-ticket[1]+1;    //为了比最大的人票数多,至少要a个水军参加投票   
        int count = a*m-a;          //count 为a个水军投票的总数,去掉给ticket[1]的票   
          
        //把count个票往别的选手上分,但要使得其他人的票数最多为max(ticket[1]-1) ,  
        for(int i = 2;i<=n;i++)  
        {  
            if(ticket[i]>=ticket[1]) //最多只能给(max - ticket[i])个,使的他的票数为max   
                count = count - (max-ticket[i]);
	        else
		        count -= a;       
        }  
          
        if(count<=0)     //如果此时票数分完了,也就是已经够了(上面已经保证每一个都不大于ticket[1])   
        {  
            printf("Case %d: %d\n",k-1,a);  
            continue;  
        }  
          
        int i;  
        //如果不够,继续加水军   
        for(i = 1;(1.0*i*m+count-i)/(n-1)>i;i++);    //i个水军吧票数给1号i票之后,把剩下的票数平分给其他的n-1个人,如果他们平均得到的票数<=i(也就是其他人票数要始终比1号少一个或多个),此时就已经够了 
	//i = ceil(count*1.0/(n-m));   上面的for循环可以简化为这个试子 
        printf("Case %d: %d\n",k-1,a+i);  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值