Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) D. Dynamic Problem Scoring 贪心

本文解析了CodeForces平台上的一道题目D,通过分析比赛中的得分规则和参赛者的答题情况,采用暴力枚举和贪心策略来解决如何通过开设小号来改变排名的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:

http://codeforces.com/contest/807/problem/D

题意:

一场比赛一共5道题,有n个参赛者,现在只关心前两个,要使第一个人最后得分比第二个人高

每道题的总分数和通过这道题的人数与总人数的比值有关,如下表

现在给出每个人的每道题的通过时间,如果没有通过,时间为-1

通过的题的的分数为这道题的总分数*(1-通过时间/250)。

现在A(第一个人)想要超过第二个人(B),A有很多小号,问你A最小需要开几个小号才能超过B,或者永远也超不过

题解:

这道题的N最大为120,现在考虑极端的例子,假设有N个人,全都通过了这道题,如果想让通过率变为最小的,也就是1/32,那么最多也只需要开32倍的小号(或者33倍?)

反之,如果通过率为0想变成1/2 也是32倍的N,所以这道题可以暴力枚举开小号的个数,然后在贪心决定这些小号在每道题上通过与否

假如A没通过这道题,那么小号自然也通过不了

假如A过了这道题,B没过,那么肯定要让这道题的通过率低,所以开的小号都不通过这道题

假如A和B都过了,但是A比B快,还是小号全都不通过

这样就只有A和B都通过了,B比A快的时候,才让小号全都通过这道题,这样这道题通过率就上升了,分数就下降了

代码:

31 int n;
32 int a[120][5], cnt[5];
33 
34 int cal(int id, int pid, int num) {
35     if (a[id][pid] == -1) return 0;
36     int maxPoint = 500, solved;
37     if (a[0][pid] == -1 || a[1][pid] == -1 || a[0][pid] < a[1][pid])
38         solved = cnt[pid];
39     else solved = cnt[pid] + num - n;
40     for (int i = 2; i <= 32; i *= 2) {
41         if (solved*i > num) break;
42         maxPoint += 500;
43     }
44     return maxPoint*(1 - a[id][pid] / 250.0);
45 }
46 
47 int main() {
48     cin >> n;
49     rep(i, 0, n) rep(j, 0, 5) {
50         cin >> a[i][j];
51         if (a[i][j] != -1) cnt[j]++;
52     }
53     rep(num, n, 40 * n) {
54         int A = 0, B = 0;
55         rep(j, 0, 5) A += cal(0, j, num);
56         rep(j, 0, 5) B += cal(1, j, num);
57         if (A > B) {
58             cout << num - n << endl;
59             return 0;
60         }
61     }
62     cout << -1 << endl;
63     return 0;
64 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值