题目
题目概要
n
n
n 枚硬币排成一列。每次选择一个正面朝上的硬币翻转,并可选择(也可以不选择)一个左边的硬币,将其翻转(无论是正面朝上还是背面朝上)。无法操作者负。
数据范围与约定
n
≤
1
0
4
n\le 10^4
n≤104 。以字符串的形式给出初始状态。输出是否先手必胜。
思路
本质是 n i m nim nim 游戏。
考虑一次操作带来的影响:
- 一个正面朝上的硬币变成了背面朝上。在 n i m nim nim 游戏中,体现为“ ⊕ \oplus ⊕ 原数字”。
- 一个左边的硬币被翻转了。在 n i m nim nim 游戏中,体现为“ ⊕ \oplus ⊕ 更小的新数字”。
所以直接使用每个正面朝上的硬币的下标进行异或即可判断。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0' or c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c and c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
inline void writeint(long long x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) writeint(x/10);
putchar((x%10)^48);
}
# define MB template < class T >
MB void getMax(T &a,const T &b){ if(a < b) a = b; }
MB void getMin(T &a,const T &b){ if(b < a) a = b; }
int main(){
int n = readint(), x = 0;
for(int i=1; i<=n; ++i)
if(getchar() == 'H')
x ^= i;
puts(x == 0 ? "Bob" : "Alice");
return 0;
}