[HDU 2509] Be the Winner (博弈、分裂游戏)
本质上是一个 Anti-Nim Game。考虑如何计算 SG 函数。
如果当前有堆\(x\)个石子,我取出任意个后,一定会把当前堆分为左右两堆,我们可以枚举左右两堆的大小\(l,r\) ,保证\(0\le l + r < x\),则有
\[SG(x) = \mathrm{mex} ( SG(l)\oplus SG(r))
\]
#include <bits/stdc++.h>
using namespace std;
const int inf = INT_MAX / 2;
using vi = vector<int>;
vi g(101, -1);
int mex(vi p) {
if (p.empty()) return 0;
ranges::sort(p);
p.resize(unique(p.begin(), p.end()) - p.begin());
for (int i = 0; i < p.size(); i++)
if (i != p[i]) return i;
return p.size();
}
int sg(int x) {
if (g[x] != -1) return g[x];
vi p;
for (int l = 0; l < x; l++)
for (int r = 0; l + r < x; r++)
p.push_back(sg(l) ^ sg(r));
return g[x] = mex(p);
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
int res = 0, f = 1;
for (int i = 1, x; i <= n; i++) {
cin >> x;
res ^= sg(x), f &= (x <= 1);
}
if ((f != 0 and res == 0) or (f == 0 and res != 0)) cout << "Yes\n";
else cout << "No\n";
return 0;
}