博弈论 _ SG函数
定义
SG函数是指:在有向图中,对于每个节点x,设从 出发共有条有向边(直接相连的边),分别达到节点,
定义为的后继节点的值构成的集合执行运算后的值
设集合S是一个非负整数集合,mex(S)就是求不属于S的最小非负整数。
例如下图:
性质及定理
性质:
- SG(i)=k,则i最大能到达的点的SG值为k−1。
- 非0可以走向0
- 0只能走向非0
定理1:同一个图上
对于一个图GG,如果SG(G)!=0,则先手必胜,反之必败
证明:
若SG(G)=!0
1.根据性质2,先手必可以走向0,
2.因此留给后手的是0,根据性质3,后手只能走向非0
3.以此类推,后手始终无法走向0,后手永远处于非0,当先手到达终点的0时,先手获胜
(由此我们可以知道,有些事是命中注定的~~~)
反之同理,必败
定理2:不同图之间
对于n个图,如果,则先手必胜,反之必败
证明(类似与Nim游戏):
-
当 时 , , 显然先手必败
(PS:结束状态必是状态①,但状态①不一定是结束状态) -
当 时,因为肯定存在一个,而根据的性质1可知,可以走到的任何一个状态,
因此,必定可以从 , 于是使得 -
当时,当移动任何一个节点时,对应的值必然减小,可以证明:
下证:
假设:xor=0xor=0,则说明移动的那个节点的值并没有变化,即从变成了kk,但是这与函数的性质1相矛盾,因此不成立
证得:若先手面对的状态是,则先手方总能使,即使后手面对的永远是必败态直到结束状态1 ,因此先手必胜!
反之,必败!
模板代码
#include<bits/stdc++.h> #define int long long #define pdd pair<double ,double > using namespace std; const int N = 110, M = 10010; int n,m; int s[N], f[M]; int sg(int x){ if(f[x]!=-1) return f[x]; unordered_set<int> S; for(int i=0;i<n;i++) //如果可以减去s[i],则添加到S中 if(x>=s[i]) S.insert(sg(x-s[i])); //求mex(),即找到最小并不在原集合中的数 for(int i=0; ; i++) if(!S.count(i)) return f[x]=i; } void solve(){ cin>>n; for(int i=0;i<n;i++) cin>>s[i]; memset(f,-1,sizeof f); cin>>m; int ans=0; while(m--){ int x;cin>>x; ans^=sg(x); } if(ans) puts("Yes"); else puts("No"); } signed main(){ int t=1; // cin>>t; while(t--) solve(); return 0; }
模板题
893. 集合-Nim游戏
题意
给定 n 堆石子以及一个由 k 个不同正整数构成的数字集合 S。
现在有两位玩家轮流操作,每次操作可以从任意一堆石子中拿取石子,每次拿取的石子数量必须包含于集合 S,最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入样例
2
2 5
3
2 4 7
输出样例
Yes
代码
#include<bits/stdc++.h> #define int long long #define pdd pair<double ,double > using namespace std; const int N = 110, M = 10010; int n,m; int s[N], f[M]; int sg(int x){ if(f[x]!=-1) return f[x]; unordered_set<int> S; for(int i=0;i<n;i++) //如果可以减去s[i],则添加到S中 if(x>=s[i]) S.insert(sg(x-s[i])); //求mex(),即找到最小并不在原集合中的数 for(int i=0; ; i++) if(!S.count(i)) return f[x]=i; } void solve(){ cin>>n; for(int i=0;i<n;i++) cin>>s[i]; memset(f,-1,sizeof f); cin>>m; int ans=0; while(m--){ int x;cin>>x; ans^=sg(x); } if(ans) puts("Yes"); else puts("No"); } signed main(){ int t=1; cin>>t; while(t--) solve(); return 0; }
作者:Anoxia_3
链接:https://www.acwing.com/solution/content/13191/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/16679003.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-09-10 21/9/9补题 [ 欧拉筛] [数组去重] | [进制转换]
2021-09-10 Java入门
2021-09-10 JAVA:类和对象基础