1. 程式人生 > 其它 >博弈論進階——Anti-SG

博弈論進階——Anti-SG

博弈論進階——\(Anti\)-\(SG\)

博弈\(——\)多年以後,\(Bob\)仍然愛慕著\(Alice\)的容顏

\(SG\)函式的拓展\(——Anti\)-\(SG\)遊戲

感謝賈志豪《組合遊戲略述——淺談SG遊戲的若干拓展及變形》一文

一、\(Anti-Nim\)遊戲

\(n\)堆石子,兩個人可以從任意一堆石頭中拿走任意顆石頭,拿走最後一個石頭的失敗
這與我們之前處理的\(Nim\)遊戲有所不同,即兩人勝利的條件發生了改變,與\(Nim\)遊戲相反,所以被稱之為\(Nim\)遊戲

結論

先手必勝當且僅當滿足下面兩種情況的一種:
(1)任意堆的石子數都為\(1\)且遊戲的\(SG\)

值為\(0\)
(2)存在堆的石子數大於\(1\)且遊戲的\(SG\)值不為\(0\)

證明:
假設有\(n\)堆石子。

  1. 每堆只有一個石子
    之前我們就證明過每一堆石子的\(SG\)值顯然是這堆石子的個數。每一堆的石子數均為\(1\)
    很容易看出:
    當有偶數堆時,也就是\(SG\)值為\(0\)時,先手必勝
    當有奇數堆時,也就是\(SG\)值為\(1\)時,先手必敗
  2. 至少兩堆石子數大於\(1\)
    考慮兩種情況,當\(SG\)\(0\)\(SG\)不為\(0\)的情況。
  • \(SG\) 不為 \(0\)
    若還有至少兩堆石子的數目大於 \(1\),則先手將 \(SG\) 值變為 \(0\) 即可;若只有一堆石子數大於 \(1\)
    ,則先手總可以將狀態變為有奇數個 \(1\)。所以,當 \(SG\) 不為 \(0\) 時先手必勝。
  • \(SG\)\(0\)
    至少有兩堆石子的數目大於 \(1\),則先手決策完之後,必定至少有一堆的石子數大於 \(1\),且 \(SG\) 值不為 \(0\),由上段的論證我們可以發現,此時,無論先手如何決策,都只會將遊戲帶入先手必勝局,所以先手必敗。
    (說實話感覺大佬賈志豪這段的證明有點問題)
    另外一種證明方式

二、\(Anti-SG\)

\(Anti-SG\)遊戲與\(SG\)遊戲不同的點僅僅在於\(Anti-SG\)是最後一個進行操作的輸。

\(SG\)函式存在這樣一個性質:
\(SG\)

\(0\)的局面不一定為終局局面。(定理一的反命題)
基於這個性質我們可以知道\(Anti-Nim\)的結論並不能直接套用在\(Anti-SG\)上面。

對於這個問題,賈志豪給出了\(SJ定理\)\((Sprague Grundy——Jia Zhihao定理)\)

\(SJ\)定理
規定當局面中所有的單一遊戲\(SG\)值為\(0\)時,遊戲結束,則先手必勝當且僅當

  1. 遊戲\(SG\)值不為\(0\)且遊戲中某個單一遊戲的\(SG\)函式大於\(1\)
  2. 遊戲\(SG\)函式為\(0\)且遊戲中沒有單一遊戲的\(SG\)函式大於\(1\)

證明(全文照搬):

我們只需要證明:

  1. 所有的終止局面為先手必勝局。(這一點顯然,證明中略去)
  2. 遊戲中的任何一個先手必敗局一定只能夠轉移到先手必勝局;
  3. 遊戲中的任何一個先手必勝局一定能夠轉移到至少一個先手必敗局。

情況一:局面的 SG 函式為 0 且遊戲中某單一遊戲的 SG 函式大於1。

∵當前局面的 SG 函式值為 0
又∵SG 函式性質
∴它所能轉移到的任何一個局面的 SG 函式值不為 0 ①
∵當前局面的 SG 函式值為 0 且遊戲中某個單一遊戲的 SG 函式大於1。
∴當前局面中必定至少有 2 個單一遊戲的 SG 函式大於 1。
又∵每次至多隻能更改一個單一遊戲的 SG 值
∴它所能轉移到的任何一個局面都至少有一個單一遊戲的 SG 值大於1。②
由①②得,情況一所能轉移到的任何一個局面都為先手必勝局。

情況二:局面的 SG 函式不為 0 且遊戲中沒有單一遊戲的 SG 函式大於 1。

顯然,當前局面一定有奇數個遊戲的 SG 函式值為 1,其餘遊戲的 SG函式值為 0。

  1. 將某個單一遊戲的 SG 值更改為大於 1 的數。
    ∵轉移前沒有單一遊戲的 SG 值大與 1,轉移將某個單一遊戲的 SG值更改為大於 1 的數。
    ∴轉移後的局面一定有且只有一個單一遊戲的 SG 值大於 1。 ③
    ∴後繼局面的 SG 值一定不為 0。 ④
    由③④得,後繼局面一定為先手必勝局。
  2. 將某個單一遊戲的 SG 值更改為 0 或 1。
    ∵轉移是將某個 SG 值為 0 的單一遊戲改成 SG 值為 1 的單一遊戲,或將某個 SG 值為 1 的單一遊戲改成 SG 值為 0 的單一遊戲。
    ∴轉移後的局面一定有偶數個 SG 值為 1 的單一局面且不含有 SG 值大於 1 的局面。
    ∴後繼局面一定為先手必勝局。

情況三:局面的 SG 函式不為 0 且遊戲中某個單一遊戲的 SG 函式大於 1

  1. 局面中只有 1 個單一遊戲的 SG 值大於 1。
    我們選擇更改 SG 值最大的單一遊戲,我們可以選擇將其更改成 0 或1 來保證轉移後的局面有且只有奇數個 SG 值為 1 的單一遊戲。
    則通過這種方式轉以後的局面為先手必敗局。
  2. 局面中有至少兩個單一遊戲的 SG 值大於 1。
    根據 SG 函式性質(2),總存在一種決策可以將後繼局面的 SG 函式值變為 0 ⑤
    ∵局面中有至少兩個單一遊戲的 SG 值大於 1
    又∵每次最多隻能更改一個單一遊戲的 SG 值
    ∴後繼局面中至少有一個遊戲的 SG 值大於 1 ⑥
    由⑤⑥得,後繼局面為先手必敗局。

情況四:局面的 SG 函式為 0 且遊戲中沒有單一遊戲的 SG 函式大於1。

當局面中所有單一遊戲的 SG 值為 0 時,遊戲結束,先手必勝。
否則,局面有且僅有偶數個 SG 值為 1 的單一遊戲,其餘遊戲的 SG
值為 0。
我們只需將其中的某一個 SG 值為 1 的單一遊戲的 SG 值變為 0,遊戲
中即可出現奇數個 SG 值為 1 的單一遊戲,到達先手必敗局。

一道模板題
code

```cpp
#include <bitset>
#include <vector>
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <map>
#include <unordered_map>
using namespace std;
using namespace std;
#define lowbit(x) x&-x
#define ll int
#define pll pair<ll,ll>
#define dob double
#define For(i,s,n) for(ll i = s;i <= n;i++)
#define mem0(a) memset(a,0,sizeof a)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a/gcd(a,b)*b
#define abs(x) x>=0?x:-x
const int N = 1e5+5;
const double eps = 1e-6;
const ll mod =  1000000007;
const ll inf = 1e9+50;

int main(){
    ios::sync_with_stdio(false);
    ll t;cin>>t;
    while(t--){
        ll n;cin>>n;
        ll sum = 0,cnt = 0;
        for(ll i = 1;i <= n;i++){
            ll x;cin>>x;
            if(x>1)cnt++;
            sum^=x;
        }
        if((sum == 0 && cnt == 0)||(sum && cnt)) cout<<"John\n";
        else cout<<"Brother\n";
    }
    return 0;
}