博弈論進階——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\)堆石子。
- 每堆只有一個石子
之前我們就證明過每一堆石子的\(SG\)值顯然是這堆石子的個數。每一堆的石子數均為\(1\)。
很容易看出:
當有偶數堆時,也就是\(SG\)值為\(0\)時,先手必勝
當有奇數堆時,也就是\(SG\)值為\(1\)時,先手必敗 - 至少兩堆石子數大於\(1\)
考慮兩種情況,當\(SG\)為\(0\)和\(SG\)不為\(0\)的情況。
- 當 \(SG\) 不為 \(0\) 時
若還有至少兩堆石子的數目大於 \(1\),則先手將 \(SG\) 值變為 \(0\) 即可;若只有一堆石子數大於 \(1\) - 當 \(SG\) 為 \(0\) 時
至少有兩堆石子的數目大於 \(1\),則先手決策完之後,必定至少有一堆的石子數大於 \(1\),且 \(SG\) 值不為 \(0\),由上段的論證我們可以發現,此時,無論先手如何決策,都只會將遊戲帶入先手必勝局,所以先手必敗。
(說實話感覺大佬賈志豪這段的證明有點問題)
另外一種證明方式
二、\(Anti-SG\)
\(Anti-SG\)遊戲與\(SG\)遊戲不同的點僅僅在於\(Anti-SG\)是最後一個進行操作的輸。
\(SG\)函式存在這樣一個性質:
\(SG\)
基於這個性質我們可以知道\(Anti-Nim\)的結論並不能直接套用在\(Anti-SG\)上面。
對於這個問題,賈志豪給出了\(SJ定理\)\((Sprague Grundy——Jia Zhihao定理)\)
\(SJ\)定理
規定當局面中所有的單一遊戲\(SG\)值為\(0\)時,遊戲結束,則先手必勝當且僅當
- 遊戲\(SG\)值不為\(0\)且遊戲中某個單一遊戲的\(SG\)函式大於\(1\)
- 遊戲\(SG\)函式為\(0\)且遊戲中沒有單一遊戲的\(SG\)函式大於\(1\)
證明(全文照搬):
我們只需要證明:
- 所有的終止局面為先手必勝局。(這一點顯然,證明中略去)
- 遊戲中的任何一個先手必敗局一定只能夠轉移到先手必勝局;
- 遊戲中的任何一個先手必勝局一定能夠轉移到至少一個先手必敗局。
情況一:局面的 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。
- 將某個單一遊戲的 SG 值更改為大於 1 的數。
∵轉移前沒有單一遊戲的 SG 值大與 1,轉移將某個單一遊戲的 SG值更改為大於 1 的數。
∴轉移後的局面一定有且只有一個單一遊戲的 SG 值大於 1。 ③
∴後繼局面的 SG 值一定不為 0。 ④
由③④得,後繼局面一定為先手必勝局。 - 將某個單一遊戲的 SG 值更改為 0 或 1。
∵轉移是將某個 SG 值為 0 的單一遊戲改成 SG 值為 1 的單一遊戲,或將某個 SG 值為 1 的單一遊戲改成 SG 值為 0 的單一遊戲。
∴轉移後的局面一定有偶數個 SG 值為 1 的單一局面且不含有 SG 值大於 1 的局面。
∴後繼局面一定為先手必勝局。
情況三:局面的 SG 函式不為 0 且遊戲中某個單一遊戲的 SG 函式大於 1
- 局面中只有 1 個單一遊戲的 SG 值大於 1。
我們選擇更改 SG 值最大的單一遊戲,我們可以選擇將其更改成 0 或1 來保證轉移後的局面有且只有奇數個 SG 值為 1 的單一遊戲。
則通過這種方式轉以後的局面為先手必敗局。 - 局面中有至少兩個單一遊戲的 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;
}