[BZOJ 1115] [POI2009] 石子游戏Kam 【阶梯博弈】

题目链接:BZOJ - 1115

 

题目分析

首先看一下阶梯博弈:

阶梯博弈是指:初始有 n 堆石子,每次可以从任意的第 i 堆拿若干石子放到第 i - 1 堆。最终不能操作的人失败。 

解法:将奇数位的石子堆做最基本的 NIM 就可以了。

WHY:对奇数位做 NIM 的必胜者总是可以胜利,因为如果从奇数位拿石子到偶数位,就相当于把这些石子拿走了,就是 NIM ;如果必败者从偶数位将石子拿到奇数位,必胜者总是可以将这些石子再向前移一个位置,就又放到了偶数位,这样一直移动的话,最终会是必胜者将这些石子拿到了 0 位置,然后必败者就不能再移动这些石子了。就相当于没有发生变化,偶数位的石子对我们的游戏就相当于没有影响。 

然后看一下这道题,要求保证总是满足单调不降。

我们对石子进行差分,即 B[i] = A[i] - A[i - 1]。那么就会发现,从第 i 堆拿走一颗石子就是相当于将 B[i] -= 1, B[i + 1] += 1,那么就是一个向后进行的阶梯 NIM 了,从后向前取奇数位的 Bi 异或一下就可以了。 

 

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int MaxN = 1000 + 5;

int T, n;
int A[MaxN], B[MaxN];

int main()
{
	scanf("%d", &T);
	for (int Case = 1; Case <= T; ++Case)
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
		for (int i = 1; i <= n; ++i) B[i] = A[i] - A[i - 1];
		int Temp = 0;
		for (int i = n; i > 0; i -= 2) Temp ^= B[i];
		if (Temp) printf("TAK\n");
		else printf("NIE\n");
	}
	return 0;
}

  

posted @ 2015-03-19 15:33  JoeFan  阅读(378)  评论(0编辑  收藏  举报