[AcWing] 894. 拆分-Nim游戏(C++实现)博弈论SG函数例题
1. 题目

2. 读题(需要重点注意的东西)
思路:
 首先要知道几个定义
公平组合游戏(ICG)
必胜状态和必败状态
SG函数
mex运算
有向图游戏的和
SG值的意义
SG值的一个定理
本题思路:
 
 本题的主要思路就是代结论,求出每个局面的SG值,但是需要注意,此题的局面有很多种,因为一堆石子(如上图a1)又可以分为两堆石子(如上图(b1,b2)、(c1,c2)),考虑所有的局面,用mex运算计算出sg值,然后代入结论:
3. 解法
---------------------------------------------------解法---------------------------------------------------
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;
const int N = 110;
int n;
int f[N];
int sg(int x)
{
    if (f[x] != -1) return f[x]; // 记忆化搜索
    unordered_set<int> S; // 用哈希表来存储
    
    // 当前状态可以变为如下局面
    for (int i = 0; i < x; i ++ )
        for (int j = 0; j <= i; j ++ )
            // 存储分出来的两堆石子sg值的异或
            S.insert(sg(i) ^ sg(j));
    for (int i = 0;; i ++ ) // mex运算求出该堆石子的sg值
        if (!S.count(i))
            return f[x] = i;
}
int main()
{
    cin >> n;
    memset(f, -1, sizeof f);
    int res = 0;
    while (n -- )
    {
        int x;
        cin >> x;
        res ^= sg(x); // 公式
    }
    if (res) puts("Yes");
    else puts("No");
    return 0;
}
 
可能存在的问题
4. 可能有帮助的前置习题
- [AcWing] 893. 集合-Nim游戏(C++实现)博弈论SG函数模板题
 
5. 所用到的数据结构与算法思想
- 博弈论
 - SG函数
 - 记忆化搜索
 
6. 总结
博弈论SG函数例题,理解思想并自己实现代码。










