2022 牛客多校(加赛)题解
E Everyone is bot 博弈
大意
n
n
n个人进行复读游戏,整个游戏中每个人能且只能选择复读一次,每次游戏可能有多轮,每一轮依次从
1
1
1到
n
n
n询问是否复读,若一轮没有人复读游戏结束。若第
i
i
i个人在整个游戏中是第
j
j
j个复读的那么他就能获得
a
i
j
aij
aij价值。特别的在整个游戏中倒数第
p
p
p个复读的人不仅得不到奖励还会被处罚。 询问所有人可能获得的最大价值。
1
<
=
a
i
j
<
=
1
e
9
,
1
<
=
p
<
=
n
1<= aij <= 1e9,1<=p<=n
1<=aij<=1e9,1<=p<=n
思路
首先因为所有人都是最优情况考虑的,被禁言是要罚的,且所有人都有办法避免被禁言即不’复读’ 所以肯定不会出现被禁言的情况 所有的
v
a
l
>
=
0
val >= 0
val>=0。
能得出一个结论 ,所有的复读行为肯定在第一轮就结束,假设我们已经知道答案第
i
i
i个人能获得的价值为
v
a
l
i
vali
vali。因为没人被禁言,一定存在第
j
j
j个人价值为
0
0
0, 如果第
i
i
i个人第一轮选择不复读,那么第j个人就会在第
1
1
1轮将第
i
i
i个人的名额抢走,让自己有获得奖励的机会,第i个人的
v
a
l
i
vali
vali就会变成0。 所以在保证不被禁言的情况下,所有人在第一轮就完成所有复读。
考虑每个人能获得的价值一定是前
k
k
k个人能获得价值,且
v
a
l
i
=
a
[
i
]
[
i
]
vali = a[i][i]
vali=a[i][i]
对p进行分类讨论来决定
k
k
k。
p
>
n
/
2
p > n / 2
p>n/2 结论: 一定是前
n
−
p
n - p
n−p个人可以获得奖励
因为当前n - p个人选择复读,编号为
n
−
p
+
1
n - p + 1
n−p+1的人若是选择复读,此时剩下还未选择的人数为
p
−
1
p - 1
p−1 则之后的所有人都会选择复读因为此时已经没有风险不会有人被禁言。
第
n
−
p
+
1
n - p + 1
n−p+1一定会被禁言所以他的选择就一定是不复读,不让自己被禁言的情况出现。那么到第n - p + 2个人选择时,就会面临相同的情况,同样不复读。如此那么前n - p个人就一定没有被禁言的风险。
p
<
=
n
/
2
p <= n / 2
p<=n/2 结论:一定是前n % p个人能复读
初看之下好像所有的人都有被禁言的风险(赛时就猜测是全0)
当实际上我们模拟一下,
n
=
7
,
p
=
3
,
p
<
=
n
/
2
n = 7 ,p = 3 ,p <= n / 2
n=7,p=3,p<=n/2 因为有 所有复读都会发生在第一轮的结论 我们可以直接从最后
p
p
p个人看起
看最后三人
5
,
6
,
7
5,6,7
5,6,7 要是第
5
5
5人复读,那么第
6
,
7
6,7
6,7人就没有风险一定会复读,第
5
5
5人就不敢复读了,
5
,
6
,
7
5,6,7
5,6,7没人敢复读
往前推三人
2
,
3
,
4
2,3,4
2,3,4 同样的原理
2
,
3
,
4
2,3,4
2,3,4同样不敢复读
最后剩下第一个人复读没有被禁言风险,因为后面没人敢复读了
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N][N];
int main()
{
int n,p;
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n%p;i++)printf("%d ",a[i][i]);//对于p > n / 2的情况 n - p = n % p
for(int i=n%p+1;i<=n;i++)printf("%d ",a[i][i]);
return 0;
}
其他题目的题解会在补题后更新
8.27 更新E题