BZOJ 1115: [POI2009]石子遊戲Kam (階梯nim)
阿新 • • 發佈:2018-02-23
limit solved sub log 一道 def ret cst 否則 Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1138 Solved: 697
[Submit][Status][Discuss]
2
2 2
3
1 2 4
TAK
Submit: 1138 Solved: 697
[Submit][Status][Discuss]
Description
有N堆石子,除了第一堆外,每堆石子個數都不少於前一堆的石子個數。兩人輪流操作每次操作可以從一堆石子中移走任意多石子,但是要保證操作後仍然滿足初始時的條件誰沒有石子可移時輸掉遊戲。問先手是否必勝。
Input
第一行u表示數據組數。對於每組數據,第一行N表示石子堆數,第二行N個數ai表示第i堆石子的個數(a1<=a2<=……<=an)。 1<=u<=10 1<=n<=1000 0<=ai<=10000
Output
u行,若先手必勝輸出TAK,否則輸出NIE。
Sample Input
22
2 2
3
1 2 4
Sample Output
NIETAK
HINT
感謝MT大牛翻譯.
Source
又是一道很神的題
題目中給出的序列是嚴格上升的,所以我們可以考慮對整個序列差分一邊
然後我們再考慮拿走石子對答案個貢獻
拿走石子實際上是減小與前面的差值,增大與後面的差值
這實際上就是一個反方向的階梯nim遊戲!
然後倒著把奇數層異或起來就好啦
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int MAXN=1e6+10,INF=1e9+10; inline char nc() { static char buf[MAXN],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++; } inline int read() {char c=nc();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=nc();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=nc();} return x*f; } int a[MAXN]; main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif int QWQ=read(); while(QWQ--) { int N=read(),ans=0; for(int i=1;i<=N;i++) a[i]=read(); for(int i=N;i>=2;i--) a[i]=a[i]-a[i-1]; for(int i=N;i>=1;i--) if( (N-i+1)&1 ) ans=ans^a[i]; puts(ans?"TAK":"NIE"); } return 0; }
BZOJ 1115: [POI2009]石子遊戲Kam (階梯nim)