P3480 [POI2009]KAM-Pebbles 阶梯NIM

Posted olinr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3480 [POI2009]KAM-Pebbles 阶梯NIM相关的知识,希望对你有一定的参考价值。

$ color{#0066ff}{ 题目描述 }$

有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数。两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏。问先手是否必胜。

(color{#0066ff}{输入格式})

多组输入,第一行一个整数u代表数据组数(1<=u<=10)

接下来共2*u行,每两行代表一组数据:

第一行只有一个整数n(1<=n<=1000),表示石子堆数;

第二行有n个整数用空格隔开,第i个整数ai表示第i堆的石子个数,保证a1<=a2<=a3...<=an。

对于每组数据,保证石子总数不超过10000。

(color{#0066ff}{输出格式})

输出u行,如果第i组数据先手必胜,输出“TAK”,否则输出“NIE”。

(color{#0066ff}{输入样例})

2
2
2 2
3
1 2 4

(color{#0066ff}{输出样例})

NIE
TAK

(color{#0066ff}{数据范围与提示})

none

(color{#0066ff}{题解})

考虑每一堆石子能拿多少,就是(a[i]-a[i-1]),差分数组

如果在i堆拿了x个石子,那么相当于i堆可拿石子数-x,i+1堆可拿石子数+x

也就是说从i堆向i+1堆拿了x个石子,这是反着的阶梯NIM!!!

#include<bits/stdc++.h>
#define LL long long
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
int a[1005050];
int main() {
    for(int T = in(); T --> 0;) {
        int n = in();
        int ans = 0;
        for(int i = 1; i <= n; i++) a[i] = in();
        for(int i = n; i >= 1; i--) a[i] -= a[i - 1];
        //注意要反着求
        for(int i = n; i >= 1; i -= 2) ans ^= a[i];
        printf(ans? "TAK
" : "NIE
");
    }
    return 0;
}

以上是关于P3480 [POI2009]KAM-Pebbles 阶梯NIM的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1137POI2009Wsp 岛屿

BZOJ 1142: [POI2009]Tab

[POI2009]?????????Gas

BZOJ 1115: [POI2009]石子游戏Kam

BZOJ 1115: [POI2009]石子游戏Kam

洛谷 P3486 [POI2009]KON-Ticket Inspector