SP20951 题解
思路
题目标题(SNIM)已经在提示我们这道题的做法了,博弈论(Nim 游戏)。
由于要求取完之后单调不降,对原石子堆 $a$ 做一个前缀差,记录在数组 $b$ 中,代表实际游戏要用到的石子堆。
假设我们在第 $i$ 堆石子中取了 $x$ 个,则 $b_i=(a_i-x)-a_{i-1}=a_i-a_{i-1}-x$,比原来少了 $x$ 个石子,但是 $b_{i+1}=a_{i+1}-(a_{i}-x)=a_{i+1}-a_i+x$,也就是将这 $x$ 个转移到了第 $i+1$ 堆。
这就是一道反着的阶梯 Nim 的模板。
所以策略如下:
-
先手将奇数堆多的石子转移到偶数堆。
-
若对方移动奇数堆,先手继续移动奇数堆,否则将对方移过来的石子移动到偶数堆。
-
在多次移动之后,先手可以先对方一步把奇数堆的石子转移到偶数堆,直到将石子转移到第 $0$ 堆,对方不能移动。
所以对答案有影响的只有奇数堆,在奇数堆上跑 Nim 游戏策略即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int t,n,ans;
int a[maxn],b[maxn];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ans=0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i]-a[i-1];
for(int i=n;i>=0;i-=2)ans^=b[i];
if(ans)puts("TAK");
else puts("NIE");
}
}

浙公网安备 33010602011771号