CF2155E Mimo & Yuyu 题解
思路
前置知识:博弈论。
考虑把每一列分开,用 SG 函数。由于 \(b_1 > b_2\) 的条件,所以第一列的点是没有用的,所以 \(SG(1) = 0\),即必败状态。接下来,需分类讨论。
当 \(n = 1\) 时,此时只有一行。模拟一下可以得到:如果当前 \(y = 2\) 时有奇数个,则先手必胜;否则,此时会放到棋盘上每一个格子的棋子数都是偶数,所以后手可以和先手走同样的移动方法,后手必胜。
否则,\(n \le 2\)。因为第二列可以由第一列推出,所以 \(SG(2) = \operatorname{mex}\{SG(1)\} = 1\)。又因为第三列可以由第二列推出,第二列又能推出第一列,所以 \(SG(3) = \operatorname{mex}\{SG(1), SG(2)\} = 2\)。以此类推。此时,只用维护 \(SG(y_1), SG(y_2), \cdots, SG(y_k)\) 的数值分别出现了多少次。如果出现了偶数次,后手可以和先手走同样的移动方法,后手必胜;如果出现了奇数次,则先手用一次操作将其变成偶数,同时先后手互换,则先手必胜。
注意:不能用异或维护,只能开数组或用 set 等。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int t, n, m, k;
int cnt[N];
void solve()
{
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= m; i++) cnt[i] = 0;
for (int i = 1, x, y; i <= k; i++)
{
scanf("%d%d", &x, &y);
if (n == 1) y = (y == 2 ? 2 : 1);
if (y > 1) cnt[y] ^= 1;
}
for (int i = 2; i <= m; i++)
{
if (cnt[i] > 0)
{
printf("Mimo\n");
return;
}
}
printf("Yuyu\n");
}
int main()
{
scanf("%d", &t);
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号