博弈论-acwing893.集合-Nim游戏

补充知识

有向图游戏

给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿着有向边方向移动,每次可以移动一步,无法移动者判负。该游戏被称为有向图游戏。任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个结点,并且从每个局面向沿着合法行动能够到达下一个局面连有向边。

这个题每一堆石子都可以看做成一个有向图

Mex运算

设S表示一个非负整数集合。定义mex(S)为求不出属于集合S的最小非负整数的运算,即:mex(S)=min(x),x属于自然数,且x不属于S

SG函数

在有向图游戏中,对于每个节点x,设从x除法共有k条有向边,分别到达结点y1,y2,...,yk,定义SG(x)为x的后继结点y1,y2,...,ykSG()函数值构成的集合再执行mex(S)运算的结果,即:SG(x)=mex(SG(y1),SG(y2),...,SG(yn))

特别的,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即:SG(G)=SG(s)

SG定理(有向图游戏的和)

G1,G2,...,Gm是m个有向图游戏。定义有向图游戏G,它的行动规则是任选某个有向图游戏Gi,并在Gi上行动一步。G被称为有向图游戏G1,G2,...,Gm的和。

有向图游戏的和SG函数在数值上等于它所包含的各个子游戏SG函数的异或和,即:SG(G)=SG(G1)SG(G2)...SG(Gm)

存在结论:

对于n个图,如果SG(G1)SG(G2)...SG(GN)0,则先手必胜,否则先手必败

acwing893.集合-Nim游戏

思路

h[i]表示的是每一堆石子有多少个,将每一个h[i]看做一张有向图

例如S=[2,5],h[1]=10
看h[1]这张有向图:

(ps:注意求SG函数需要mex()函数求,看其定义不要搞乱了)

#include<iostream>
#include<unordered_set>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 100, M = 10010;

int n,m;
int f[M],s[N]; //f表示可能出现过的sg函数值,s表示可选正整数的集合

int sg(int x)
{
    if(f[x] != -1) return f[x]; // 如果算出来过sg(x)就直接返回f[x]
    
    unordered_set<int> S; // 用来存储该节点下一步的节点他们的sg函数值
    for(int i = 0; i < n; i ++)
    {
        int sum = s[i];
        if(x >= sum) S.insert(sg(x - sum)); // 如果存在下一步,将下一步节点sg函数值存入
    }
    
    // mex操作
    for(int i = 0;;i ++)
    {
        if(!S.count(i)) return f[x] = i; 
    }
    
}

int main()
{
    cin >> n ;
    for(int i = 0; i < n; i ++) cin >> s[i];
    
    cin >> m;
    memset(f,-1,sizeof(f));
    
    int res = 0;
    for(int i = 0; i < m; i ++)
    {
        int x; // x表示这一堆石子的数量
        cin >> x;
        res ^= sg(x);
    }
    
    if(res) puts("Yes");
    else puts("No");
    
    return 0;
}
posted @   r涤生  阅读(103)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示