bzoj1874: [BeiJing2009 WinterCamp]取石子游戏 组合游戏
2015-01-02 23:18
246 查看
首先是最简单的Nim游戏:有N堆石子,每次从一堆中取出不为空的石子,不能取者为负。判断先手是否必胜。有一个小小的结论:后手必胜当且仅当所有石子的异或和为0。
再麻烦一点。规定每次取的石子个数,比如每次只能取1,3,4。我们先考虑只有一堆石子。
(以下摘自那个博客)
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。
对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Grundy函数g如下:g(x)=mex{ g(y) | y是x的后继 },这里的g(x)即sg[x]
sg[0]=0,f[]={1,3,4},
x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;
x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;
x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;
x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;
x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;
以此类推.....
x 0 1 2 3 4 5 6 7 8....
sg[x] 0 1 0 1 2 3 2 0 1....
在这里,那个异或和的结论还是正确的。如果sg
=0,那么就存在后手必胜的策略。
但是如果有多堆石子,应该怎么办?直接把所有的SG全部异或起来,也是判断是否是0。
知道了这些结论,那道题也就成了傻题。前面是裸的SG,后面再枚举一下即可。
关于 (sg[a[i]-b[j]]^(ans^sg[a[i]]))==0 假如除第i堆没取的值如果xor sg[a[i]-b[j]] ==0的话 就说明这对于对方是必败条件,也就是我方的必胜条件。
再麻烦一点。规定每次取的石子个数,比如每次只能取1,3,4。我们先考虑只有一堆石子。
(以下摘自那个博客)
首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、mex{2,3,5}=0、mex{}=0。
对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Grundy函数g如下:g(x)=mex{ g(y) | y是x的后继 },这里的g(x)即sg[x]
sg[0]=0,f[]={1,3,4},
x=1时,可以取走1-f{1}个石子,剩余{0}个,mex{sg[0]}={0},故sg[1]=1;
x=2时,可以取走2-f{1}个石子,剩余{1}个,mex{sg[1]}={1},故sg[2]=0;
x=3时,可以取走3-f{1,3}个石子,剩余{2,0}个,mex{sg[2],sg[0]}={0,0},故sg[3]=1;
x=4时,可以取走4-f{1,3,4}个石子,剩余{3,1,0}个,mex{sg[3],sg[1],sg[0]}={1,1,0},故sg[4]=2;
x=5时,可以取走5-f{1,3,4}个石子,剩余{4,2,1}个,mex{sg[4],sg[2],sg[1]}={2,0,1},故sg[5]=3;
以此类推.....
x 0 1 2 3 4 5 6 7 8....
sg[x] 0 1 0 1 2 3 2 0 1....
在这里,那个异或和的结论还是正确的。如果sg
=0,那么就存在后手必胜的策略。
但是如果有多堆石子,应该怎么办?直接把所有的SG全部异或起来,也是判断是否是0。
知道了这些结论,那道题也就成了傻题。前面是裸的SG,后面再枚举一下即可。
关于 (sg[a[i]-b[j]]^(ans^sg[a[i]]))==0 假如除第i堆没取的值如果xor sg[a[i]-b[j]] ==0的话 就说明这对于对方是必败条件,也就是我方的必胜条件。
#include <cstring> #include <algorithm> #include <cstdio> #include <cmath> using namespace std; int n,m,ans,sg[1100],a[100],b[100]; bool mark[100]; int getint() { int res;char c; while(c=getchar(),c<'0'||c>'9'); res=c-'0'; while(c=getchar(),c>='0'&&c<='9') res=res*10+c-'0'; return res; } void init() { for(int i=1;i<=1000;i++) { memset(mark,0,sizeof(mark)); for(int j=1;j<=m;j++) if(i-b[j]>=0) mark[sg[i-b[j]]]=1; for(int j=0;j<=100;j++) if(!mark[j]) {sg[i]=j;break;} } } int main() { n=getint(); for(int i=1;i<=n;i++) a[i]=getint(); m=getint(); for(int i=1;i<=m;i++) b[i]=getint(); init(); for(int i=1;i<=n;i++) ans^=sg[a[i]]; if(!ans) printf("NO\n"); else printf("YES\n"); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if( (sg[a[i]-b[j]]^(ans^sg[a[i]]))==0 ) { printf("%d %d\n",i,b[j]); return 0; } } } return 0; }
相关文章推荐
- BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏(SG函数)
- [BeiJing2009 WinterCamp] bzoj1874 取石子游戏 [博弈论]
- [BZOJ1874][BeiJing2009 WinterCamp]取石子游戏(博弈SG函数)
- 【博弈论】【SG函数】【枚举】bzoj1874 [BeiJing2009 WinterCamp]取石子游戏
- bzoj1874 [BeiJing2009 WinterCamp]取石子游戏 nim游戏 sg函数
- 1874: [BeiJing2009 WinterCamp]取石子游戏 - BZOJ
- bzoj 1874 [BeiJing2009 WinterCamp]取石子游戏
- bzoj 1874: [BeiJing2009 WinterCamp]取石子游戏 Nim游戏+SG函数
- [BZOJ1874][BeiJing2009 WinterCamp]取石子游戏
- BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏 [Nim游戏 SG函数]
- BZOJ1874: [BeiJing2009 WinterCamp]取石子游戏
- bzoj1874: [BeiJing2009 WinterCamp]取石子游戏
- [BZOJ1874][BeiJing2009 WinterCamp]取石子游戏
- 【BZOJ 1874】 [BeiJing2009 WinterCamp]取石子游戏
- [BZOJ 1874] [BeiJing2009 WinterCamp] 取石子游戏 【博弈论 | SG函数】
- bzoj 1874: [BeiJing2009 WinterCamp]取石子游戏
- BZOJ_P1874 [BeiJing2009 WinterCamp]取石子游戏(博弈+SG函数)
- BZOJ 4532: [BeiJing2014 WinterCamp] 珠链
- BZOJ4533 [BeiJing2014 WinterCamp] 数据
- BZOJ4533: [BeiJing2014 WinterCamp] 数据