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的位置有兩個棋子。
大家知道,雖然偶爾不夠浪漫,但是Rabbit和Grass都是冰雪聰明的女生,如果每次都是Rabbit先走棋,請輸出最後的結果。
#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
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;
}