問題概要
Nが与えられる。( N≦108 )
2人で次のゲームを行う。 Nの素因数を一つ選択し、相手にNをその素因数で割った商を新たなNとして渡す。 このとき同じ数であれば何回割っても良い。 先手後手どちらが勝つか。
解法
基本となる素数をNimの山として、ある素数の数はあるNimの山の石の数に対応する。 素因数は sqrt(N)で、 Nimは素因数の各個数を列挙したもののXORを取ればよい。
Nimってなんだと言う人はこちらへ。 競プロにおけるNim、Grundy数とNimK
ソース
#include <bits/stdc++.h> using namespace std; using VS = vector<string>; using LL = long long; using VI = vector<int>; using VVI = vector<VI>; #define SZ(a) int((a).size()) #define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++) LL N; LL ans = 0LL; int main() { cin.tie(0); ios_base::sync_with_stdio(false); cin >> N; VI a; LL NN = N; for (int i = 2; i*i <= NN; i++) { int cnt = 0; while (N%i == 0) { cnt++; N /= i; } if (cnt)a.push_back(cnt); } if (N > 1) { a.push_back(1); } FOR(i, 0, SZ(a)) { ans ^= a[i]; } cout << (ans == 0 ? "Bob" : "Alice") << "\n"; return 0; }