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