目前有3堆石子,每堆石子个数也是任意的,双方轮流从中取出石子,规则如下:1)每一步应取走至少一枚石子;每一步只能从某一堆中取走部分或全部石子;2)如果谁不能取谁就失败。
Bouton定理:
必败状态当且仅当x1^x2^x3==0
SG函数和SG定理:
对于任意状态x,SG(x)=mex(S),S是x后继状态中SG函数值集合,mex(S)表示不在S内的最小非负整数
SG(x)=0当且仅当x为P
有这样一个游戏,是多个游戏共同进行,每个游戏都执行到底时才算整个游戏结束,每次一个选手可以把一个游戏进行一步。
对于这样的游戏它的某状态的g(x)值,为每个子游戏的现在所处的状态的g(x)值xor起来的结果
裸Nim游戏
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,a; int main(){ while(scanf("%d",&n)!=EOF){ a=read();n--; while(n--) a^=read(); if(a) puts("Yes"); else puts("No"); } }
Nim先手获胜方案数
找有多少堆数量大于其他堆异或的值,(取这堆后异或就是0了)
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=1005; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,a[N]; int main(){ while(scanf("%d",&n)!=EOF&&n){ int s=0,ans=0;; for(int i=1;i<=n;i++) a[i]=read(),s^=a[i]; if(s!=0) for(int i=1;i<=n;i++){ int x=a[i],t=s^a[i];; if(x>t) ans++; } printf("%d ",ans); } }