题目大意是和普通的NIM游戏一样,但是却是取到最后一个是输的,天真的以为就是反过来,其实并不是这样的
结论
先手必胜的条件为
①:所有堆的石子数均=1,且有偶数堆。
②:至少有一个堆的石子数>1,且石子堆的异或和≠0。
证明
一、当所有堆的石子数均为1时
(1):石子异或和(t)=0,即有偶数堆。此时显然先手必胜。
(2):t≠0,即有奇数堆。此时显然先手必败。
二、当有一堆的石子数>1时,显然t≠0
(1):总共有奇数堆石子,此时把>1的那堆取至1个石子,此时便转化为一.(2),先手必胜。
(2):总共有偶数堆石子,此时把>1的那堆取完,同样转化为一.(2),先手必胜。
三、当有两堆及以上的石子数>1时
(1):t=0,那么可能转化为以下两个子状态:
①:至少两堆及以上的石子数>1且t≠0,即转为三.(2)。
②:至少一堆石子数>1,由二可知此时必胜。
(2):t≠0,根据Nim游戏的证明,可以得到总有一种方法转化为三.(1)状态。
观察三我们发现,三.(2)能把三.(1)扔给对面,而对面只能扔给你三.(2)或必胜态。所以当三.(2)时先手必胜。综上,所有堆的石子数均=1且t=0/至少有一个堆的石子数>1且t≠0时,先手必胜。
参考HDU2509
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> int main() { int ts;//确定是T态还是S态 int n; int i,j; int m[100]; int Nuheap;//充裕堆的个数 while(scanf("%d",&n)!=EOF) { Nuheap=0; ts=0; for(i=1;i<=n;i++) { scanf("%d",&m[i]); if(m[i]>=2) Nuheap++; ts^=m[i]; } if((ts==0&&Nuheap>=2)||(ts!=0&&Nuheap==0)) //我们知道 如果当前是T2态,那么只能转变成S1或者S2态,此时对手应用正确的方法必胜,所以这个是必败点,同理S0态也是必败点; { printf("No "); } else { printf("Yes "); } } return 0; }