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

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

Input

第一行输入正整数T,表示数据的组数。对于每组数据,第一行为两个正整数n,m(1<=m<=n<=100000)。
第二行为n 个空格隔开的整数。表示第i 个选手的得票数

Output
对于每组数据,输出一行,格式为'Case t: x',t 为数据的组号,x 为题目要求的结果
Sample Input
2
3 2
2 3 3
4 2
1 2 3 4
Sample Output
Case 1: 4
Case 2: 5
题目说让第一个人成为最多的票数(通过水军进行增加),用二分尝试水军的数量。想将a0=a[0]+x;(x是水军的数量)。下面剩下num=x*(m-1)个票。将这些票分配给剩下的人,这里需要注意水军只能给同一个人投x票。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 100005;
int n, m, mapp[MAXN];
/*直接二分查找*/ 
bool ok(int x) {
    int a0 = mapp[0] + x;
    LL num = (LL)x*(m-1); //可能爆int 
    for(int i = 1; i < n; ++i) {
        if(mapp[i] >= a0) //存在比a[0]加过水军还大的,说明水军不够 
            return false;
        if(mapp[i] + x < a0) //水军最多给同一个人投x票 
            num -= x;
        else
            num -= (a0-1-mapp[i]);
    }
    if(num <= 0) //num>0说明水军不够,在加 
        return true;
    return false;
}
int main()  
{  
    int T;
    ios::sync_with_stdio(false);//关闭同步
    cin >> T;
    for(int t = 1; t <= T; ++t) {
        cin >> n >> m;
        int k = 0;
        for(int i = 0; i < n; ++i) {
            cin >> mapp[i];
            if(mapp[i] >= mapp[k])
                k = i;
        }
        if(k == 0) //已经是票数最多的 
            cout << "Case " << t << ": 0" << endl;
        else if(n == m) //不可能成功的情况 
            cout << "Case " << t << ": Impossible" << endl;
        else {
            int l = 0, r = 100000, mid;
            while(l < r) {
                mid = (l+r)/2;
                if(ok(mid) ){
                    r = mid;
                }
                else {
                    l = mid+1;
                } 
            }
            cout << "Case " << t << ": " << l << endl;
        }
    }
    return 0;
} 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值