先看官方题解:
这个游戏叫做Turning Turtles,它的本质就是Nim游戏。那么它到底是如何转化为Nim游戏的呢?让我们一步一步来分析。

首先,我们先将局面分解一下,每一次我们只考虑一枚硬币。
不妨设所有硬币全部背面朝上的局面为局面0
假设现在N枚硬币,只有第1枚是正面朝上的。该局面只能转化为全部硬币背面朝上的局面。我们假定该局面为 局面1,则局面1可以转化为局面0。
假设只有第2枚是正面朝上的。该局面可以转化为:只有硬币1正面朝上;全部硬币背面朝上。我们假定该局面为 局面2,局面2可以转化为局面1和局面0。
同理我们可以推定,第i枚硬币正面朝上的局面为局面i,局面i可以转化为局面0..i-1。

现在,我们考虑把给定的局面拆成单个硬币的局面集合,比如给定了{HHTHTTHT},其中H表示正面朝上,T表示背面朝上。那么就是当前局面={局面1,局面2,局面4,局面7}。每一次我们可以改变其中个一个局面,当出现局面0时就从集合中删去。
这样一看是不是就变成了Nim游戏了?然而事实并没有那么简单。

进一步分析,若同时存在i,j(j<i)两枚硬币正面朝上。我们将这个局面拆成2个单一的局面:即局面i和局面j。
在反转i的时候我们考虑从局面i转移到局面j,那么我们会有两个局面j。
表示第j枚被反转了2次,也就是回到了背面朝上的状态。
那么我们得到这个游戏一个性质:当出现两个同样的局面时,等价于这两个局面合并变成了局面0。

这种情况在Nim游戏中是没有的,那么它会对Nim游戏的状态造成影响么?
我们想一想,在Nim游戏中,如果出现两个数量相同的堆时,比如A[i]=A[j]。在计算Nim游戏状态时我们采用的xor操作,xor有交换律和结合律。则我们可以变成:
(A[i] xor A[j]) xor Other
因为A[i] = A[j],所以A[i] xor A[j] = 0。上式实际就是:
0 xor Other
也就是说在原Nim游戏中,若出现了两个数量相同的堆时,实际上这两堆已经不对总局面造成影响了,也就可以认为这两对合并为了一个数量为0的堆。

到此,我们可以发现这个硬币游戏完全满足Nim游戏的规则,其解答也满足Nim游戏的性质,这题也就很简单的转化为了普通的Nim游戏。在实际的博弈游戏中会发现很多都是可以转化为Nim游戏模型。如何正确的建立模型和转化游戏模型也就是解决博弈游戏一个很重要的手段。

比如Nimble游戏:
游戏开始时有许多硬币任意分布在楼梯上,共N阶楼梯从地面由下向上编号为0到N。游戏者在每次操作时可以将任意一枚硬币向下移动,直至地面。游戏者轮流操作,将最后一枚硬币移至地面(即第0阶)的人获胜。在双方都采取最优策略的情况下,对于给定的初始局面,问先手必胜还是先手必败。
每一枚硬币仍然对应了一个石子堆,向下移动就等价于从石子堆里面取出石子。

同样的例子还有很多,有些游戏甚至需要做好几次转换才能移动到Nim游戏模型,在之后我们就会见到。

先看0 0 0 0 0 0 0 0 这个状态,这是终结点。因此sg值为0
再看1 0 0 0 0 0 0 0 这个状态,只能把第一个硬币变成正面朝上,因此它的后继只能为0号局面sg=mex{0}=1。
0 1 0 0 0 0 0 0这个状态,alice可以选择把第一枚硬币变成1还是不变,因此它的后继是0号局面或者1号局面,sg=mex{0,1}=2
...
然后容易发现规律,在只有一枚硬币正面朝上的情况下,如果它在第i位置上,则它的sg值为i。
那么我们会去猜想,是否对于多个硬币正面朝上的情况就是它们的sg值异或的结果呢?
但是我们又发现这个于nim游戏还是有些不一样之处,即nim游戏中我从一堆石子中取石子,是对其他游戏没有影响的。也就是说这里单个局面之间是相互关联的。
进一步分析,若存在i,j(i<j)两枚硬币正面朝上,我们将这个局面拆成2个单一的局面,局面i和局面j。在翻转i的时候我们考虑从局面i转移到局面j,那么我们会有两个相同的局面j。表示局面j被翻转了两次,也就是回到了背面朝上的状态。那么我们得到了这个游戏的一个性质,当出现两个相同的局面时,等价于这两个局面合并为局面0.
我们想一想,在nim游戏中,如果出现两个相同堆时,比如A[i]=A[j]。在计算nim游戏状态我们采用xor操作,而xor满***换律与结合律。则我们可以变成:
(A[i]xorA[j])xor other
即 0 xor other
也就是在原nim游戏中,如果出现了两个数量相同的堆时,实际上这两个堆已经不对总局面造成影响了,也就可以认为这两堆合并为一个数量为0的堆。

神奇的定理:局面的sg值为单一硬币存在的sg值的异或和。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string s;
    int N;
    cin>>N;
    cin >> s;
    int nim = 0; 
    for(int i = 0; i < N; i++){
        nim ^= (s[i]=='H' ? i+1 : 0);

    }
    if(nim > 0) {
        cout << "Alice" << endl;
    }
    else {
        cout << "Bob" << endl;
    }
    return 0;
}