题目链接:http://codeforces.com/contest/773/problem/B
题意:
给了你一个不知真假的cf的判题标准(该题基础分由通过人数和题交人数的比值决定,该题可得分数还要减去通过时间/250,保证通过时间<=119),然后一号用户想赢二号用户,造了1e9+7个小号(因为:假设某一题1号过得快,它可以通过让小号wa来增加这个题的基础分让自己多拿一点分,如果他过的慢,那么他就可以多让小号a掉让这个题的基础分减小让这题不值钱),然后问题来了,这里还有个条件,假设1号用户没过这个题,那么它的小号也交不了a,就是这个额外条件让这个题不能二分。
做法:
小号的作用无疑是放大了分数,但是假设1号用户有一道a不了的题,但是这个题2号过的很快,那么如果1号用户有很多小号的话,这个题就默认有了很高的分数,这就对1号是不利的,这种时候就宁愿让人少一点,可能在减少这道题分数的情况下其他题也能凑到。
比如样例
十七人
66 15 -1 42 90
67 108 104 16 110
其他人的题目总通过人数为12 9 12 13 11人
如果二分,第一次的比值太大,1 2 3 5 的分值都是3000,4是500,但是这样无疑是放大了3号题,1号也过不了,那么还不如小一些,5个人让分数为500,1000,500,500,500,也就够了。
因为比值在1/32之后就没有了,所以最大人数其实不用1e9+7,只要120*32大概40000也就够了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100005;
ll n,yes[6];
ll peo[3][6];
ll gain(ll ac,ll all){
if(ac*2>all) return 500;
else if(ac*4>all) return 1000;
else if(ac*8>all) return 1500;
else if(ac*16>all) return 2000;
else if(ac*32>all) return 2500;
else return 3000;
}
ll Cal(ll bas,ll tim){
return bas-tim*bas/250;
}
int ck(ll m){
ll fi=0,se=0;
for(int i=1;i<=5;i++){
if(peo[1][i]==peo[2][i]) continue;
if(peo[1][i]<peo[2][i]){
fi=fi+Cal(gain(yes[i],n+m),peo[1][i]);
se=se+Cal(gain(yes[i],n+m),peo[2][i]);
//printf("pro=%d so=%d\n",i,gain(yes[i],n+m));
}
else{
if(peo[1][i]==250){
fi=fi+Cal(gain(yes[i],n+m),peo[1][i]);
se=se+Cal(gain(yes[i],n+m),peo[2][i]);
//printf("pro=%d so=%d\n",i,gain(yes[i],n+m));
}
else{
fi=fi+Cal(gain(yes[i]+m,n+m),peo[1][i]);
se=se+Cal(gain(yes[i]+m,n+m),peo[2][i]);
//printf("pro=%d so=%d\n",i,gain(yes[i]+m,n+m));
}
}
}
return fi>se;
}
int main(){
scanf("%lld",&n);
int tmp=n;
for(int i=1;i<=n;i++){
int f=0;
for(int j=1;j<=5;j++){
int x;
scanf("%d",&x);
if(x!=-1) yes[j]++,f=1;
if(i<=2){
if(x==-1) x=250;
peo[i][j]=(ll)x;
}
}
if(f==0)tmp--;
}
n=tmp;
for(int i=0;i<=50000;i++){
if(ck(i)){
printf("%d\n",i);
return 0;
}
}
printf("-1\n");
return 0;
}
/*
2
66 15 -1 42 90
67 108 104 16 110
*/