Description:
nn堆石子,每次可以把一堆石子分成若干份,任意两份之间的差且每堆都要>=m>=m,问先后手输赢。
Solution:
sgsg函数裸题,但是不能枚举后继,复杂度过高。发现这样分事实上只有n−−√n种数量不同的石子,并且由于xorxor只和奇偶性有关,那么利用分块优化枚举即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, f, mk;
int sg[N], vis[N], p[N];
void dfs(int n) {
if(vis[n]) {
return;
}
vis[n] = 1;
stack<int> s;
while(!s.empty()) {
s.pop();
}
for(int i = 2, j = 0; i <= n; i = j + 1) {
j = n / (n / i);
int t = n / i;
dfs(t);
dfs(t + 1);
for(int k = i; k <= min(i + 1, j); ++k) {
int r = n % k, A = (k - r) & 1, B = r & 1;
s.push((A * sg[t]) ^ (B * sg[t + 1]));
}
}
++mk;
while(!s.empty()) {
p[s.top()] = mk;
s.pop();
}
for(int i = 0; ; ++i) {
if(p[i] != mk) {
sg[n] = i;
break;
}
}
}
int main() {
int T;
scanf("%d%d", &T, &f);
for(int i = 1; i < f; ++i) {
vis[i] = 1;
}
for(int kase = 1; kase <= T; ++kase) {
int n, x, sum = 0;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &x);
dfs(x);
sum ^= sg[x];
}
printf("%d%c", sum ? 1 : 0, kase == T ? '\n' : ' ');
}
return 0;
}