HDU 3032 Nim or not Nim

题意

给你 n 堆石子,每次取可以从任意一堆中取任意多个,或者将一堆分为非零的两堆。

这是一个典型的 Multi-SG 问题

可以使用 SG 函数来解决。举个栗子,比如一堆 3 个石子,你可以一次取 0, 1, 2, 3 个或者将它分成 \((1, 2)\) 两堆, 因此 $SG(3) = mex { SG(0), SG(1), SG(2), SG(3), SG((1, 2)) = SG(1) \oplus SG(2) } $
那么这个问题本质上还是一个 Nim 游戏, 可以直接用 SG 函数来解决。
同时,这样每次拆分成两堆的 Multi-SG 游戏,打表找规律后 发现这样的性质。

\[SG(x) = \begin{cases} x-1 \ (x \operatorname{mod} 4 = 0) \\ x\ \ \ \ \ \ \ (x \operatorname{mod} 4 = 1 \& 2) \\ x+1 \ (x \operatorname{mod} 4 = 3) \end{cases} \]

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define N 100010
#define M 1010

using namespace std;
int T, n, a, ans;

int read() {
	int s = 0, f = 0; char ch = getchar();
	while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

int main() {
	T = read();
	while (T--) {
		ans = 0;
		n = read();
		for (int i = 1; i <= n; i++) {
			a = read();
			if (a % 4 == 0) a--;
			else if (a % 4 == 3) a++;
			ans ^= a;
		}
		if (!ans) puts("Bob");
		else puts("Alice");
	}
	return 0;
}
posted @ 2020-09-07 21:11  Kersen  阅读(63)  评论(0编辑  收藏  举报