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;
}
posted @ 2026-01-04 16:43  lucasincyber  阅读(1)  评论(0)    收藏  举报