传送门: https://csacademy.com/contest/round-67/task/suffix-flip/
题意: 给出一个长度为 n (1<= n <= 1e5) 的二进制字符串, 定义翻转操作为: 从任意一个为1的位置开始将其后的所有1和0互换(既1010可以翻转为0101或者1001)
两个人轮流翻转字符串, 问先手胜负.
博弈论:
- 如果一个状态能转移到必败态, 那这个状态一定是必胜态.
- 如果一个状态所有能转移到的状态都是必胜态, 那这个状态是必败态.
寻找必败态:
显然, 0是最简单的必败态
此时, 默认0之后所有的状态都是必败
- 1 可以转移到必败态, 所以 1 一定是必胜态.
- 10 只能转移到 1, 所以 10 是必败态.
- 11 可以转移到 10, 所以 11 是必胜态.
- 100 只能转移到 11, 所以 100 是必败态.
- 依次类推, 得到下图:
此时不难夯一发结论: 结尾为 1 的时候先手必胜, 反之必败.
如何证明?
假设一串字符 s 以 0 结尾为必败态, 那么将最后一个字符由 0 改为 1 的字符 s’ 一定为必胜态.
如果一串字符 s 以 1 结尾并且这串字符中包含不止一个 1.
那么所有的操作都会改变末尾的 1 的值, 使得该串字符变为以 0 结尾.
归纳假设可证之.
结论出来之后代码就很短了.
#include <iostream>
#include <cstring>
const int MAX = 1e5+10;
char s[MAX];
int n;
int main() {
int n;
scanf("%d", &n);
scanf("%s", s);
printf("%c\n", s[n-1]);
return 0;
}
2018-02-01