HDU 1907 John(尼姆博弈之ANTI-SG游戏)

题目连接:HDU 1907 John

尼姆博弈之ANTI-SG游戏。

定义概念:
孤单堆:只有一根火柴的堆
充裕堆:有两根或两根以上火柴的堆
T态:所有堆火柴数异或值为0
S态:所有堆火柴数异或值大于0
T0,S0:所有堆为孤单堆的T/S情形
T1,S1:有一个充裕堆的T/S情形
T2,S2:有两个或以上充裕堆的T/S情形
事实上,孤单堆的根数异或只会影响二进制的最后一位,但充裕堆会影响高位(非最后一位)。一个充裕堆,高位必有一位不为0,则所有根数异或不为0,故T1态实际上不存在。
[定理5]:S0态,即仅有奇数个孤单堆,必败。T0态必胜。
证明:
S0态,其实就是每次只能取一根。每次第奇数根都由己取,第偶数根都由对 方取,所以最后一根必己取。败。同理, T0态必胜

[定理6]:S1态,只要方法正确,必胜。
证明:
若此时孤单堆含奇数个火柴,把充裕堆取完;否则,取成一根。这样,就变成奇数个孤单堆,由对方取。由定理5,对方必输。己必胜。 #
[定理7]:S2态不可转一次变为T0态。
证明:
充裕堆数不可能一次由2变为0。得证。
[定理8]:S2态可一次转变为T2态。
证明:
由定理1,S态可转变为T态,S态可一次转变为T态,又由定理6,S2态不可转一次变为T0态,所以转变的T态为T2态。
[定理9]:T2态,只能转变为S2态或S1态。
证明:
由定理2,T态必然变为S态。由于充裕堆数不可能一次由2变为0,所以此时的S态不可能为S0态。命题得证。
[定理10]:S2态,只要方法正确,必胜.
证明:
方法如下:
1) S2态,就把它变为T2态。(由定理8)
2) 对方只能T2转变成S2态或S1态(定理9)
若转变为S2, 转向1)
若转变为S1, 这己必胜。(定理5)
[定理11]:T2态必输。
证明:同10。
综上所述,对于ANTI-SG游戏:
必输态有: T2,S0
必胜态: S2,S1,T0.

那么由以上可以看出,有两种情况。

一是全是孤单堆,二是至少有一堆不是孤单的。

那么对于第一种情况,如果有奇数个孤单堆,先手负,这对应S0,否则先手胜,这对应T0。对于第二种情况,与SG游戏结果相同,初始局面SG值亦或不为零,先手胜,这对应S2,S1,否则,先手负,这对应T2。只有一个非孤单堆是出不来T的,所以对于第二种情况,只要出现T那么一定是T2,不可能是T1。

#include <iostream>

using namespace std;

int T,N;

int main()
{
    cin >> T;
    while(T--)
    {
        cin >> N;
        int ans = 0;
        int flag = false;
        int num;
        for(int i = 1;i <= N;i++)
        {
            cin >> num;
            if(num > 1)
                flag = true;
            ans ^= num;
        }
        if(!flag)
        {
            if(N % 2)
                cout << "Brother" << endl;
            else
                cout << "John" << endl;
        }
        else
        {
            if(ans)
                cout << "John" << endl;
            else
                cout << "Brother" << endl;
        }


    }
    return 0;
}




你可能感兴趣的:(HDU 1907 John(尼姆博弈之ANTI-SG游戏))