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); }}