POJ 2975 Nim(BOJ 7685)

http://poj.org/problem?id=2975 https://www.acmicpc.net/problem/7685

https://vjudge.net/problem/POJ-2975 https://vjudge.net/problem/Baekjoon-7685

問題概要

  • $N\ (\leq 1000)$個の山にある石の数$A_i\leq10^9$が与えられ、その盤面でNimの自分の手番が回ってきたとする。その手番で取れる行動のうち、勝利できる手の個数を数え上げよ

解法メモ

  • 与えられた状態での総XOR$\bigoplus_{i=1}^N A_i=0$の時はそもそも負けが確定しているので0を出力する。
  • そうでない場合、勝利できる手=操作後の総XORが0になる手 となる。
  • 取る山を決めた時、その山の石の個数を$(\bigoplus_{i=1}^N A_i)\oplus A_i$にすれば総XORを0にすることができ、これ以外の値で0にすることはできない。
  • 各$i$についてこの値が$A_i$以下であるものを数えればよい
#include <iostream>
#include <vector>
#define rep(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    while (true) {
        int n;
        cin >> n;
        if (n == 0) break;
        vector<int> v(n);
        rep(i, n) cin >> v[i];

        int all_xor = 0;
        rep(i, n) all_xor ^= v[i];

        if (all_xor == 0) {
            cout << 0 << '\n';
            continue;
        }

        int ans = 0;
        rep(i, n) if ((all_xor ^ v[i]) <= v[i]) ans++;

        cout << ans << '\n';
    }
    return 0;
}