P3480-[POI2009]KAM-Pebbles【阶梯博弈】

正题

题目链接:https://www.luogu.com.cn/problem/P3480


题目大意

\(n\)个石头堆上进行\(\text{Nim}\)游戏,不过需要满足每次操作前后都有\(a_i\leq a_{i+1}(\ i\in[1,n)\ )\)


解题思路

让每一个\(b_i=a_i-a_{i-1}\)就是一个阶梯博弈问题了。

阶梯博弈问题:\(n\)堆石头,第\(i\)堆石头有\(a_i\)个,每次一个玩家可以取走若干个第一堆的石头,或者将第\(i\)堆的任意个石头丢到第\(i-1\)堆里面。

这个问题的\(sg\)函数就是编号为奇数的石头数量的异或和,具体证明的话就是如果只看奇数堆石头,那么转移奇数的堆里的石头就相当与去掉一些石头。所以如果奇数堆必胜的玩家一定会转移奇数堆的,因为如果后手转移偶数堆里的那么先手再把新的转走状态就不会改变。

所以直接做就好了,时间复杂度\(O(Tn)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1100;
int T,n,a[N];
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=n;i>=1;i--)
            a[i]=a[i]-a[i-1];
        int ans=0;
        for(int i=n;i>=1;i-=2)
            ans^=a[i];
        puts(ans?"TAK":"NIE");
    }
    return 0;
}
posted @ 2021-01-13 19:52  QuantAsk  阅读(72)  评论(0编辑  收藏  举报