poj 2975 Nim(博弈)

                                 Nim

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5232   Accepted: 2444

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 n piles 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:

 11110111101 

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

【思路】

博弈

设v=a1^a2…^an,对于i,如果ai>(v^ai)则先手可以把ai变为v^ai,此时局面必败。累计ans即可。

【代码】

 1 #include<cstdio>
 2 using namespace std;
 3
 4 int n,a[1001];
 5
 6 int main() {
 7     while(scanf("%d",&n)==1 && n) {
 8         int v=0,ans=0;
 9         for(int i=0;i<n;i++)
10             scanf("%d",&a[i]) , v^=a[i];
11         for(int i=0;i<n;i++)
12             if((v^a[i])<a[i]) ans++;
13         printf("%d\n",ans);
14     }
15     return 0;
16 }
时间: 2024-11-13 16:13:31

poj 2975 Nim(博弈)的相关文章

POJ 2975 Nim 尼姆博弈

题目大意:尼姆博弈,求先手必胜的情况数 题目思路:判断 ans=(a[1]^a[2]--^a[n]),求ans^a[i] < a[i]的个数. #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<stdio.h> #include<stdlib.h> #include<queue> #include<

poj 2975 Nim 尼姆博弈,求取胜方案数

Nim Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5002   Accepted: 2313 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 mor

[原博客] POJ 2975 Nim 统计必胜走法个数

题目链接题意介绍了一遍Nim取石子游戏,可以看上一篇文章详细介绍.问当前状态的必胜走法个数,也就是走到必败状态的方法数. 我们设sg为所有个数的Xor值.首先如果sg==0,它不可能有必胜走法,输出0. 对于任意一堆有a[i]个石子,若sg Xor a[i] <= a[i] ,那么我们就可以在a[i]里面取出sg Xor a[i]个石子,使得剩下石子Xor和为0,于是ans++.然后输出ans. 注意C/C++语言中^操作比<操作优先级低. #include<iostream> #

POJ - 2975 Nim

我们之前的\(Nim\)游戏都已经知道当\(Nim\)和为\(0\)时是必败的. 那我们就刻意制造这种情况.因为一次只能改一堆石头,不能制造几个数异或消去\(sum\)的情况,所以只用考虑将\(a[i]\)替换为\(a[i]?sum\)的情况就行了. 注意要保证\(a[i]?sum<a[i]\). #include<cstdio> #include<cstdlib> int n, a[1002], sum, ans; int read() { int x = 0, f = 1

POJ 2975 Nim(普通nim)

题目链接 #include<iostream> #include<cstdio> using namespace std; int main() { int n,k[1005]; int sum,cnt; while(scanf("%d",&n)&&n) { sum=0,cnt=0; for(int i=1;i<=n;i++) { scanf("%d",&k[i]); sum^=k[i]; } if(su

POJ 2234 Matches Game(Nim博弈裸题)

Description Here is a simple game. In this game, there are several piles of matches and two players. The two player play in turn. In each turn, one can choose a pile and take away arbitrary number of matches from the pile (Of course the number of mat

POJ Cutting Game(Nim博弈+grundy数)

Description Urej loves to play various types of dull games. He usually asks other people to play with him. He says that playing those games can show his extraordinary wit. Recently Urej takes a great interest in a new game, and Erif Nezorf becomes th

ACM学习历程—HDU 3915 Game(Nim博弈 &amp;&amp; xor高斯消元)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3915 题目大意是给了n个堆,然后去掉一些堆,使得先手变成必败局势. 首先这是个Nim博弈,必败局势是所有xor和为0. 那么自然变成了n个数里面取出一些数,使得xor和为0,求取法数. 首先由xor高斯消元得到一组向量基,但是这些向量基是无法表示0的. 所以要表示0,必须有若干0来表示,所以n-row就是消元结束后0的个数,那么2^(n-row)就是能组成0的种数. 对n==row特判一下. 代码:

UVA 11859 Division Game (Nim博弈)

题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32746 题意:有一个n*m(1<=n,m<=50)矩阵,每个元素均为2~10000之间的正整数,两个游戏者轮流操作.每次可以选一行中的1个或者大于1的整数,把他们中的每个数都变成它的某个真因子,比如12可以边长1,2,3,4或者6,不能操作的输. 分析:考虑每个数包含的素因子个数(比如12=2*2*3包含3个素因子),则让一个数"变成它的素因子"