-数论-博弈论- [CF1215D]Ticket Game

题目描述

Link

Solution

非常不错的一道博弈论题目,模型有点像Bash博弈。

首先这道题我们可以这么理解:有两堆石头,其中一堆有 $x$ 个石头,只能放 $n$ 次石头,每次能放的石头数量不超过 $9$ 个,另一堆有 $y$ 个石头,能放 $m$次,每次能放的石头数量也不超过 $9$ 个。每次操作可以放 $0$ 个石头 。先手后手轮流操作,两堆石头都可以放,如果两堆石头能放的次数用完了,当且仅当两堆石头个数相等时后手赢,问后手是否有必胜策略。

根据题意我们可以得出这样一个结论:当且仅当 $n=m$ 以及 $x=y$ 时,后手必赢。

所以我们为了达到这个局面,必须要让其中一堆石头的个数小于另一堆石头并且这一堆石头能放的次数大于另一堆石头,或者是两堆石头的石头个数以及能放的次数均相等。

我们再来看题目,题目中说了 $n + m$ 是偶数,所以又可以得出 $|n - m|$ 一定是偶数。

所以如果出现了 $n < m$ 且 $x > y$ 的局面,要想让后手必赢,必须满足 $x - y = 9 * (m - n)$。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 200010
char a[MAXN];
int n, p, q, x, y;
int main() {
scanf("%d", &n);
scanf("%s", a + 1);
for (int i = 1; i <= n / 2; i++) {
if (a[i] != '?') p += a[i] - '0';
else x++;
}
for (int i = n / 2 + 1; i <= n; i++) {
if (a[i] != '?') q += a[i] - '0';
else y++;
}
if (x < y) std::swap(x, y), std::swap(p, q);
if (p > q) {
puts("Monocarp");
return 0;
}
if (p == q && x == y) {
puts("Bicarp");
return 0;
}
x -= y;
q -= p;
if (q == (x / 2) * 9) {
puts("Bicarp");
return 0;
}
else {
puts("Monocarp");
return 0;
}
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2019/09/18/102/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论