POJ 2975 - Nim
http://poj.org/problem?id=2975
概要
Nim というゲームは二人で行い,n 個の石の山から交互に,1つの山から好きな数だけ石を取り除いていき,最終的にすべて取り除いたプレイヤーの勝ちである.
このゲームには,両プレイヤーが perfect にプレイしたときに先手が負ける losing という状態があり,これは各山の石の数を k[1], ..., k[n] とすると,k[i] の xor が 0 のときであることが知られている.
現在の状態から losing 状態にする一手を winning move という.
n 個の山のそれぞれの石の数が与えられるので,その状態からの winning move が何種類存在するかを答える.
制約
- 1 < = n < = 1000
- 1 < = k[i] < = 1000000000
解法
k[i] の xor の値を X とすると,i 番目の山から石を取り除いて losing 状態にするには,k[i] を X xor k[i]
に変えればいい.
この操作を行えるのは X xor k[i]
が k[i] より小さいときのみ.
poj/2975.cc1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 int main() 6 { 7 int N; 8 while (scanf("%d", &N) != EOF && N != 0) { 9 vector<long long> ks(N); 10 long long x = 0LL; 11 for (int i = 0; i < N; i++) { 12 scanf("%lld", &ks[i]); 13 x ^= ks[i]; 14 } 15 16 int c = 0; 17 for (int i = 0; i < N; i++) { 18 if ((x ^ ks[i]) < ks[i]) { 19 ++c; 20 } 21 } 22 printf("%d\n", c); 23 } 24 return 0; 25 }