Description
Solution
博弈论好题。
偶数个的石子堆是可以模仿操作的,所以就没有用了。所以就成了一些01串。
每个石子的移动有点像Nim,仔细想想发现就是一堆生成两堆的Nim,把SG异或起来就行了,数据范围这么小,SG直接暴力枚举。
第一步的话就是枚举\(i,j,k\),看看第\(i\)堆\(-1\),第\(j,k\)堆\(+1\)的SG是否为\(0\)就好了。
Code
const int N = 21 + 5;
int SG[N], a[N], n, bac[100];
void main() {
int t = read();
while (t--) {
n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
SG[n] = 0;
for (int i = n - 1; i; --i) {
memset(bac, 0, sizeof bac);
for (int j = i + 1; j <= n; ++j)
for (int k = j; k <= n; ++k) bac[SG[j] ^ SG[k]] = 1;
for (int j = 0; j < 100; ++j)
if (!bac[j]) {
SG[i] = j;
break;
}
}
int ans = 0, cnt = 0, x = -1, y = -1, z = -1;
for (int i = 1; i <= n; ++i)
if (a[i] % 2) ans ^= SG[i];
for (int i = 1; i <= n; ++i)
if (a[i]) {
for (int j = i + 1; j <= n; ++j) {
for (int k = j; k <= n; ++k) {
if ((ans ^ SG[i] ^ SG[j] ^ SG[k]) == 0) {
cnt++;
if (x + y + z < 0) x = i - 1, y = j - 1, z = k - 1;
}
}
}
}
printf("%d %d %d\n%d\n", x, y, z, cnt);
}
}