bzoj 1228 [SDOI2009]E&D 博弈论

题面

题目传送门

解法

显然,这个游戏可以拆成多个游戏的和

那么,我们就可以使用SG定理

定义\(SG(x,y)\)表示同一组石子中分别有\(x\)个石子和\(y\)个石子的\(SG\)

发现\(x,y≤10^9\),然后打表找规律

可以发现,若\(x,y\)都为奇数,那么\(SG(x,y)=0\)

否则,\(SG(x,y)=SG(\lceil\frac{x}{2}\rceil,\lceil\frac{y}{2}\rceil)+1\)

那么求解SG值就变成\(O(log\ x)\)

代码

#include <bits/stdc++.h>
#define N 110
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
	x = 0; int f = 1; char c = getchar();
	while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int SG(int x, int y) {
	if (x > y) swap(x, y);
	if (x % 2 == 1 && y % 2 == 1) return 0; 
	return SG((x + 1) / 2, (y + 1) / 2) + 1;
}
int main() {
	int T; read(T);
	while (T--) {
		int n, ans = 0; read(n);
		for (int i = 1; i <= n / 2; i++) {
			int x, y; read(x), read(y);
			ans ^= SG(x, y);
		}
		if (ans) cout << "YES\n";
			else cout << "NO\n";
	}
	return 0;
}

posted @ 2018-08-14 19:04  谜のNOIP  阅读(152)  评论(0编辑  收藏  举报