题目:https://www.luogu.com.cn/problem/P3480
题意:有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数。两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏。问先手是否必胜。
题解:这个可以看做一个反向的阶梯博弈,首先先对原数组做一个差值c[i]=a[i]-a[i-1],c[i]意味着相当于前面一个,我这个能取多少,因为要满足题目说的非递减,如果i是个偶数,给i位置拿走c[i]个,那么c[i+1]就变成了了c[i+1]+=c[i],相当于把前面一个数量拿给后面那个了,这个时候后手把叠加到i+1位置的c[i]个再拿走,相当于把i+1位置拿走c[i]个,也就意味着把c[i]这个数量继续叠加个后面i+2,而i+2也是偶数,相当于无用功了,奇数的情况做nim博弈就可以了,相当于对c数组做一个反向的阶梯博弈。
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
//#include <unordered_map>
//#include <unordered_set>
//#include <bits/stdc++.h>
//#define int long long
#define pb push_back
#define pii pair<int, int>
#define mpr make_pair
#define ms(a, b) memset((a), (b), sizeof(a))
#define x first
#define y second
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 9;
using namespace std;
inline int read() {
char ch = getchar();
int s = 0, w = 1;
while (ch < '0' || ch > '9') {
if (ch == '-') w = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0', ch = getchar();
}
return s * w;
}
int c[N];
int a[N];
signed main() {
int T;
T = read();
while (T--) {
int n = read();
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
c[i] = a[i] - a[i - 1];
}
int res = 0;
for (int i = n; i >= 1; i -= 2) res ^= c[i];
if (res)
puts("TAK");
else
puts("NIE");
}
return 0;
}