SG函数

SG 函数

先定义,SG 函数对应有向无环图(DAG)上的一种游戏:有一枚棋子在起点上,每次可以沿着边往后移动,谁无法移动谁就输了。

公平组合游戏可以转换成他,只需要将局面中的所有状态看成一个节点,合法行动看成有向边。

判断必胜需要求解的就是起点的 SG

对于终点(没有出边),SG=0

对于其他点 u,设它的出去的点为 v,则 SG(u)=mex(SG(v1),SG(v2),)

mex 表示没有出现的最小自然数,如 mex(2,3)=0,mex(1,0)=2,mex(0)=1

然后对于起点,若 SG=0 必败,反之必胜。

证明:

  1. 0 局面 SG=0 先手必败。
  2. 对于当前局面若 SG0,那么说明可以到达 0,走到 SG=0 的点上,那么抛给对手就是 SG=0
  3. SG=0,说明无法到达 0,那么只能给对手 SG0

若先手局面为 SG0,那么他可以给对手为0,然后对手只能给他非0,最后对手肯定得到全0,必败,先手必胜。

反之,若为0,那么他只能给对手非0,对手给他0,最后他肯定得到全0,必败,后手必胜。

那有的同学肯定好奇:SG为什么不直接取0/1?

那是因为可能会出现多张有向图的情况,此时的结论同 nim:将各SG异或,如果为0,先手必败,否则必胜。

设总值为 x

证明分三步,类似于 nim

  1. 0 局面 x=0 先手必败。

  2. 对于当前局面若 x0,存在某种方式将其变为 0

    考虑 x 的最高的为 1 二进制位(记为 k),原序列中肯定有至少一个(奇数个)图的SG第 k 位为 1。(设为 ai)所以 aix<ai(前面的位保持不变,然后第 k 位变为 0,后面就算均增加也会减少)。那么由于 mex=ai 时可以走到 [1,ai),所以,让这个有向图走到 SG=aix 的点上。那么新的异或值就是 i=1naix=xx=0,抛给对手一个 x=0 的局面。

  3. 对于当前局面若 x=0,不存在任何方式将其变为 0

    用反证法,假设存在某种方式,且走动的记为 ai,那么有 j=1nai=0,且 j=1i1ajaij=i+1naj=0,两个式子异或,其余的数都消去,剩下 aiai=0,即 ai=ai,而 mex 定义为没有出现过的最小者,只能走到 [1,ai),矛盾,所以不存在。

而当先手的局面 x>0 时,可以构造 x=0,后手又给出 x>0 的局面,先手再给予 x=0 的局面 ,后手总是持有 x=0 的局面,而最终必败状态全 0 就是 x=0,所以后手必定会取到,即后手必败。

反之 x=0,先手不管怎么搞 x>0,后手再将其变为 0,所以先手总是持有 x=0 的局面,而最终必败状态全 0 就是 x=0,所以先手必定会取到,即先手必败。

所以,我们只需要计算异或和,判断是否等于零即可。

对于本题,只需要分堆考虑,对于每一堆,只需要将石子个数当作状态,然后考虑集合中可以取的(比如 1,2,3,那么就向 x1,x2,x3 连边),求一遍 SG 即可。

#include<cstdio>
#include<vector>
using namespace std;
const int N=110;
bool st[N];
int k,s[N],n,x,res,f[N*N];
int sg(int x){
    if(f[x])return f[x];
    vector<int>g;
    for(int i=1;i<=k;++i)
        if(x>=s[i])g.push_back(sg(x-s[i]));
    for(int v:g)st[v]=1;
    for(int i=0;;++i)
        if(!st[i]){
            for(int v:g)st[v]=0;
            return f[x]=i;
        }
}
int main(){
    scanf("%d",&k);
    for(int i=1;i<=k;++i)scanf("%d",s+i);
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        int x;
        scanf("%d",&x);
        res^=sg(x);
    }
    if(res)puts("Yes");
    else puts("No");
    return 0;
}

本文作者:wscqwq

本文链接:https://www.cnblogs.com/wscqwq/p/17651966.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wscqwq  阅读(25)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起