Vasya and Petya take part in a Codeforces round. The round lasts for two hours and contains five problems.
For this round the dynamic problem scoring is used. If you were lucky not to participate in any Codeforces round with dynamic problem scoring, here is what it means. The maximum point value of the problem depends on the ratio of the number of participants who solved the problem to the total number of round participants. Everyone who made at least one submission is considered to be participating in the round.
Pay attention to the range bounds. For example, if 40 people are taking part in the round, and 10 of them solve a particular problem, then the solvers fraction is equal to 1 / 4, and the problem’s maximum point value is equal to 1500.
If the problem’s maximum point value is equal to x, then for each whole minute passed from the beginning of the contest to the moment of the participant’s correct submission, the participant loses x / 250 points. For example, if the problem’s maximum point value is 2000, and the participant submits a correct solution to it 40 minutes into the round, this participant will be awarded with 2000·(1 - 40 / 250) = 1680 points for this problem.
There are n participants in the round, including Vasya and Petya. For each participant and each problem, the number of minutes which passed between the beginning of the contest and the submission of this participant to this problem is known. It’s also possible that this participant made no submissions to this problem.
With two seconds until the end of the round, all participants’ submissions have passed pretests, and not a single hack attempt has been made. Vasya believes that no more submissions or hack attempts will be made in the remaining two seconds, and every submission will pass the system testing.
Unfortunately, Vasya is a cheater. He has registered 109 + 7 new accounts for the round. Now Vasya can submit any of his solutions from these new accounts in order to change the maximum point values of the problems. Vasya can also submit any wrong solutions to any problems. Note that Vasya can not submit correct solutions to the problems he hasn’t solved.
Vasya seeks to score strictly more points than Petya in the current round. Vasya has already prepared the scripts which allow to obfuscate his solutions and submit them into the system from any of the new accounts in just fractions of seconds. However, Vasya doesn’t want to make his cheating too obvious, so he wants to achieve his goal while making submissions from the smallest possible number of new accounts.
Find the smallest number of new accounts Vasya needs in order to beat Petya (provided that Vasya’s assumptions are correct), or report that Vasya can’t achieve his goal.
题意
对于动态计分的 Codeforces Round ,已知每题的 score 是根据 Round 参加人数和该题过题人数计算,两者之比结合上图得出该题的分数。某人在该题的得分为 score×(1−t/250) 其中 t 表示通过该题的时间。
已知参加该场比赛的所有参加者的过题情况(包括 Vasya 和 Petya),问如何通过增加新的参赛者(尽量少),使得 Vasya 的最终得分高于 Petya。
解题思路
已知每题的 score 是根据该题的过题人数 / Round 总人数得出的。且在一定的比例区间内,分数是一个定值( score 函数为一个分段函数)。
故统计每题现有人数的过题人数,根据过题人数,可以知道使得该题 score 到达下一档的最少总参数人数。(此处枚举 5 题,每题最多枚举新的总参数人数 5 次)。
在得到枚举的总参数人数后(令其为 变量 participants
),根据其对 Vasya 和 Petya 的得分进行判断(判断因贪心使得 Vasya 尽可能高于 Petya)。
对于新的总参数人数,对任意一题 pid ,存在若干种状态:
- Vasya 未通过此题。根据题意则新参赛的人无法通过此题,则比例为 原通过人数 / 新的总参赛人数
- Petya 未通过此题。此时应使得此题的 score 尽可能高,以拉开两人的差距。故决定 score 的比例为 原通过人数 / 新的总参赛人数
- Vasya 通过此题的时间晚于 Petya 。此时应使得此题的 score 尽可能低,以减小两人的差距。故应使得新参赛的人都通过此题。
- Vasya 通过此题的时间早于 Petya 。此时应使得此题的 score 尽可能高,以拉开两人的差距。故决定 score 的比例为 原通过人数 / 新的总参赛人数
代码
#include<bits/stdc++.h>
using namespace std;
int n, a[120][5], cnt[5];
int getScore(int pid, bool isPetya, int participants)
{
if(a[isPetya][pid] == -1) return 0;
int maxPoint = 500, solved;
if(a[0][pid] == -1 || a[1][pid] == -1 || a[0][pid] < a[1][pid]) {
solved = cnt[pid];
} else {
solved = participants - n + cnt[pid];
}
for(int i=2;i<=32;i*=2)
if(solved * i > participants) break;
else maxPoint += 500;
return maxPoint * (1.0 - a[isPetya][pid] / 250.0);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<5;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j] != -1) cnt[j]++;
}
vector<int> v;
v.push_back(n);
for(int i=0;i<5;i++)
for(int j=2;j<=32;j*=2)
if(cnt[i]*j >= n)
v.push_back(cnt[i]*j);
sort(v.begin(), v.end());
for(int i=0;i<v.size();i++)
{
if(i && v[i] == v[i-1]) continue;
int Vasya = 0, Petya = 0;
for(int j=0;j<5;j++)
Vasya += getScore(j, false, v[i]);
for(int j=0;j<5;j++)
Petya += getScore(j, true, v[i]);
if(Vasya > Petya) {
printf("%d\n", v[i] - n);
return 0;
}
}
printf("-1\n");
}