HDU 3032 Nim or not Nim?
取走-分割游戏
这种游戏允许取走某些东西,然后将原来的一个游戏分成若干个相同的游戏。
例1、Lasker’s Nim游戏:每一轮允许两种操作之一。(1)从一堆石子中取走任意多个(2)将一堆数量不少于2的石子分成都不为空的两堆。
分析:很明显,g(0)=0,g(1)=1。
状态2的后继有0,1和(1,1),它们的SG函数值分别是0,1和0,所以g(2)=2。状态3的后继有0,1,2和(1,2),它们的SG函数值分别是0,1,2和3,所以g(3)=4。
状态4的后继有0,1,2,3,(1,3)和(2,2),它们的SG函数值分别是0,1,2,4,5和0,所以g(4)=3。在推一些,我们得到:我们推测:对于所有的k>=0,有g(4k+1)=4k+1;g(4k+2)=4k+2;g(4k+3)=4k+4;g(4k+4)=4k+3。
请自行证明。
假设游戏初始时有3堆,分别有2、5和7颗石子。三堆的SG函数值分别是2、5和8,它们的Nim和等于15。所以要走到P状态,就要使得第三堆的SG值变成7,可以将第三堆分成按1和6分成两堆。
View Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> #include<string> #define LL long long using namespace std; int main( ) { int n,T; while( scanf( "%d",&T )==1 ) { while( T-- ) { int s = 0,m; scanf( "%d",&n ); for( int i = 0 ; i < n ; i ++ ) { scanf( "%d",&m ); if( m % 4 == 0 ) s ^= ( m - 1 ); else if( m % 4 == 3 ) s ^= ( m + 1 ); else s ^= m; } if( s != 0 ) puts( "Alice" ); else puts( "Bob" ); } } //system( "pause" ); return 0; }