Nim
有n堆石子,每堆有ai颗石子,Alice和Bob轮流从非空的石子堆中取走至少一颗石子。Alice先取,去逛所有石子的一方获胜。当双方都采取最优策略时,谁会获胜?
1<=n<=1^6
1<=ai<=10^9
INPUT:
3
1 2 4
OUTPUT:
Alice
注意这个结论成立:
a1 XOR a2 XOR a3 XOR ……XOR an ≠ 0 ==> 必胜态
a1 XOR a2 XOR a3 XOR ……XOR an = 0 ==> 必败态
所以呢,非0则Alice获胜,为0则Bob获胜
《挑战程序》上的证明如下:
一旦从XOR为0的状态取走至少一颗石子,XOR就一定会变成非0。因此,可以证实必败之后肯定是必胜。
--------------------
观察XOR的二进制表示最高位的1,选取石子数的二进制表示对应位也为1的某堆石子。
只要从中取走使得该位变为0,且其余XOR中的1也反转的数量的石子,XOR就可以变成0。
同时,看了看这几篇博文感觉更加详细
http://blog.csdn.net/lgdblue/article/details/15809893
http://blog.csdn.net/acm_cxlove/article/details/7854530
第一个博客中的例子就很好理解^_^
核心代码:
int N;
void solve(){
int x=0;
for(int i=0;i<N;i++) x^A[i];
if(x!=0) puts("Alice");
else puts("Bob");
}
hduoj1849
Rabbit and Grass
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3350 Accepted Submission(s): 2496
说是下棋,其实只是一个简单的小游戏而已,游戏的规则是这样的:
1、棋盘包含1*n个方格,方格从左到右分别编号为0,1,2,…,n-1;
2、m个棋子放在棋盘的方格上,方格可以为空,也可以放多于一个的棋子;
3、双方轮流走棋;
4、每一步可以选择任意一个棋子向左移动到任意的位置(可以多个棋子位于同一个方格),当然,任何棋子不能超出棋盘边界;
5、如果所有的棋子都位于最左边(即编号为0的位置),则游戏结束,并且规定最后走棋的一方为胜者。
对于本题,你不需要考虑n的大小(我们可以假设在初始状态,棋子总是位于棋盘的适当位置)。下面的示意图即为一个1*15的棋盘,共有6个棋子,其中,编号8的位置有两个棋子。
![](https://i-blog.csdnimg.cn/blog_migrate/6a067d51d92b3f8822e1ce20cac5a5b2.jpeg)
大家知道,虽然偶尔不够浪漫,但是Rabbit和Grass都是冰雪聪明的女生,如果每次都是Rabbit先走棋,请输出最后的结果。
2 3 5 3 3 5 6 0
Rabbit Win! Grass Win!
#include <cstdio>
int main(){
int n;
while(scanf("%d",&n)!=EOF){
if(n==0) break;
int ans=0,x;
for(int i=0;i<n;i++){
scanf("%d",&x);
ans^=x;
}
if(ans==0) puts("Grass Win!");
else puts("Rabbit Win!");
}
return 0;
}
POJ1704
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 9007 | Accepted: 2899 |
Description
![](https://i-blog.csdnimg.cn/blog_migrate/c76b52797bb489f0387716c46010da41.jpeg)
Georgia and Bob move the chessmen in turn. Every time a player will choose a chessman, and move it to the left without going over any other chessmen or across the left edge. The player can freely choose number of steps the chessman moves, with the constraint that the chessman must be moved at least ONE step and one grid can at most contains ONE single chessman. The player who cannot make a move loses the game.
Georgia always plays first since "Lady first". Suppose that Georgia and Bob both do their best in the game, i.e., if one of them knows a way to win the game, he or she will be able to carry it out.
Given the initial positions of the n chessmen, can you predict who will finally win the game?
Input
Output
Sample Input
2 3 1 2 3 8 1 5 6 7 9 12 14 17
Sample Output
Bob will win Georgia will win
棋盘游戏~
将棋子两两整体考虑,然后就可以转化成Nim啦~
【1】如果为偶数个棋子的话:两两之间的间隔作为每堆石子的个数。
将俩个里面右边的棋子左移->取石子。
将俩个里面左边的棋子左移.距离变大,石子增多,这里不同于Nim,但是再将右边的棋子左移就又变成Nim了,所以也不影响~
这样呢,所有的棋子之间的间隔变成0也就是取完了石子,达到必胜态。
间隔为0-->不管前面的棋子怎么动,只要挪动跟他成对的后面的那个棋子到相邻位置就好了。
---------------
【2】如果为奇数个棋子。设置一个坐标为0的就好了~
#include <cstdio>
#include <algorithm>
#define maxn 10005
using namespace std;
int P[maxn],n;
void solve(){
if(n%2!=0){ //奇数
P[n++]=0;
}
sort(P,P+n);
int ans=0;
for(int i=1;i<n;i+=2){
ans^=(P[i]-P[i-1]-1);
}
if(ans==0) puts("Bob will win");
else puts("Georgia will win");
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&P[i]);
}
solve();
}
return 0;
}