链接:http://acm.hdu.edu.cn/showproblem.php?pid=1850
题意: nim博弈先手赢的方法数:
思路:通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动);
定义P-position和N-position,其中P代表Previous,N代表Next。直观的说,上一次move的人有必胜策略的局面是P-position,也就是“后手可保证必胜”或者“先手必败”,现在轮到move的人有必胜策略的局面是N-position,也就是“先手可保证必胜”。更严谨的定义是:1.无法进行任何移动的局面(也就是terminal position)是P-position;2.可以移动到P-position的局面是N-position;3.所有移动都导致N-position的局面是P-position。
对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当sum(n)=a1^a2^...^an=0,其中^表示异或(xor)运算;所以当面对一个局面的时候,通过拿一堆石头中的某些使其sum=0即为胜利, sum(n-1)=k 表示前n-1 项的结果, 若an>=sum(n-1), 则表示an可以通过拿石头使其sum(n)=0;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 #include <string> 6 #include <stdlib.h> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const LL Mod= 1e9+7; 11 int a[105]; 12 int main( ) 13 { 14 int N; 15 while( scanf( "%d", &N )==1, N ){ 16 int temp=0, ans=0; 17 for( int i=0; i<N; ++ i ){ 18 scanf( "%d", &a[i] ); 19 temp^=a[i]; 20 } 21 if( temp==0 )puts( "0" ); 22 else{ 23 for( int i=0; i<N; ++ i ) 24 if( (a[i]^temp)<=a[i] )ans++; 25 printf( "%d\n", ans ); 26 } 27 } 28 return 0; 29 }