其他分享
首页 > 其他分享> > POJ 2975 NIM

POJ 2975 NIM

作者:互联网

Nim

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7650   Accepted: 3623

Description

Nim is a 2-player game featuring several piles of stones. Players alternate turns, and on his/her turn, a player’s move consists of removing one or more stones from any single pile. Play ends when all the stones have been removed, at which point the last player to have moved is declared the winner. Given a position in Nim, your task is to determine how many winning moves there are in that position.

A position in Nim is called “losing” if the first player to move from that position would lose if both sides played perfectly. A “winning move,” then, is a move that leaves the game in a losing position. There is a famous theorem that classifies all losing positions. Suppose a Nim position contains npiles having k1, k2, …, kn stones respectively; in such a position, there are k1 + k2 + … + kn possible moves. We write each ki in binary (base 2). Then, the Nim position is losing if and only if, among all the ki’s, there are an even number of 1’s in each digit position. In other words, the Nim position is losing if and only if the xor of the ki’s is 0.

Consider the position with three piles given by k1 = 7, k2 = 11, and k3 = 13. In binary, these values are as follows:

 111
1011
1101
 

There are an odd number of 1’s among the rightmost digits, so this position is not losing. However, suppose k3 were changed to be 12. Then, there would be exactly two 1’s in each digit position, and thus, the Nim position would become losing. Since a winning move is any move that leaves the game in a losing position, it follows that removing one stone from the third pile is a winning move when k1 = 7, k2 = 11, and k3 = 13. In fact, there are exactly three winning moves from this position: namely removing one stone from any of the three piles.

Input

The input test file will contain multiple test cases, each of which begins with a line indicating the number of piles, 1 ≤ n ≤ 1000. On the next line, there are n positive integers, 1 ≤ ki ≤ 1, 000, 000, 000, indicating the number of stones in each pile. The end-of-file is marked by a test case with n= 0 and should not be processed.

Output

For each test case, write a single line with an integer indicating the number of winning moves from the given Nim position.

Sample Input

3
7 11 13
2
1000000000 1000000000
0

Sample Output

3
0

Source

Stanford Local 2005

大致题意:

尼姆游戏,最后一次取空的人获胜

有N堆,每堆有num个,每次从一堆中取至少一个

解题思路:

SG问题,SG(X)=X

若a1^a2^…^an=0,必败态

在证明Nim游戏的SG函数的“根据这个判断被判为N-position的局面一定可以移动到某个P-position”命题时,

有这么一段证明:对于某个局面(a1,a2,...,an),若a1^a2^...^an不为0,一定存在某个合法的移动,将ai改变成ai'后满足a1^a2^...^ai'^...^an=0。

不妨设a1^a2^...^an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的最高位那个1是怎么得到的)。这时ai^k<ai一定成立。则我们可以将ai改变成ai'=ai^k,此时a1^a2^...^ai'^...^an=a1^a2^...^an^k=k^k=0。

由此,我们可以知道,对任意的当前状态S,只需将某堆石头a[i]变为S^a[i]即可使得整个局面的SG值为0,即变为必败态。(当然,为了保证操作合法,应当有S^a[i]<a[i],S^a[i]=a[i]时相当于不操作,不合法)

令ans=a1^a2^…^an,如果需要构造出异或值为0的数,而且由于只能操作一堆石子,所以对于某堆石子ai,现在对于ans^ai,就是除了ai以外其他的石子的异或值,如果ans^ai<=ai,那么对于ai的话,是可以减小到ans^ai的值,,此时a1^a2^...^ai'^...^an=a1^a2^...^an^ans=ans^ans=0。然后使得所有数的异或值为0,也即转移到了必败态。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 1001
int N,a[MAX],sum,ans;
int main()
{
    while(scanf("%d",&N)!=EOF && N)
    {
    	  ans=0;sum=0;
          for(int i=1;i<=N;i++)
          {
          	    scanf("%d",&a[i]);
          	    sum^=a[i];
		  }
		  for(int i=1;i<=N;i++)
		  	    if((sum^a[i])<a[i])
		  	          ans++;
		  printf("%d\n",ans);
	}
	return 0;
} 

 

标签:move,Nim,ai,NIM,winning,POJ,losing,position,2975
来源: https://blog.csdn.net/qq_40421671/article/details/94443679