bzoj1413 [ZJOI2009]取石子游戏
Description
在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排。游戏由两个人进行,两人轮流操作,每次操作者都可以从最左或最右的一堆中取出若干颗石子,可以将那一堆全部取掉,但不能不取,不能操作的人就输了。 Orez问:对于任意给出一个初始一个局面,是否存在先手必胜策略。
Input
文件的第一行为一个整数T,表示有 T组测试数据。对于每组测试数据,第一行为一个整数n,表示有n堆石子;第二行为n个整数ai,依次表示每堆石子的数目。
Output
对于每组测试数据仅输出一个整数0或1。其中1表示有先手必胜策略,0表示没有。
Sample Input
1
4
3 1 9 4
4
3 1 9 4
Sample Output
0
数据范围
对于30%的数据 n≤5 ai≤105
对于100%的数据 T≤10 n≤1000 每堆的石子数目≤109
数据范围
对于30%的数据 n≤5 ai≤105
对于100%的数据 T≤10 n≤1000 每堆的石子数目≤109
正解:博弈论。
这道题实在是太神辣。。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 6 using namespace std; 7 8 int fl[1005][1005],fr[1005][1005],a[1005],n; 9 10 il int gi(){ 11 RG int x=0,q=1; RG char ch=getchar(); 12 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 13 if (ch=='-') q=-1,ch=getchar(); 14 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 15 return q*x; 16 } 17 18 il void work(){ 19 n=gi(); 20 for (RG int i=1;i<=n;++i) fl[i][i]=fr[i][i]=a[i]=gi(); 21 for (RG int k=1;k<n;++k){ 22 for (RG int i=1,j,p,q;i<=n-k;++i){ 23 j=i+k,p=fl[i][j-1],q=fr[i][j-1]; 24 if (a[j]==q) fl[i][j]=0; 25 else if ((a[j]<p && a[j]<q) || (a[j]>p && a[j]>q)) fl[i][j]=a[j]; 26 else if (a[j]>=p && a[j]<q) fl[i][j]=a[j]+1; 27 else fl[i][j]=a[j]-1; 28 p=fr[i+1][j],q=fl[i+1][j]; 29 if (a[i]==q) fr[i][j]=0; 30 else if ((a[i]<p && a[i]<q) || (a[i]>p && a[i]>q)) fr[i][j]=a[i]; 31 else if (a[i]>=p && a[i]<q) fr[i][j]=a[i]+1; 32 else fr[i][j]=a[i]-1; 33 } 34 } 35 puts(a[1]==fl[2][n] ? "0" : "1"); return; 36 } 37 38 int main(){ 39 #ifndef ONLINE_JUDGE 40 freopen("game.in","r",stdin); 41 freopen("game.out","w",stdout); 42 #endif 43 RG int T=gi(); 44 while (T--) work(); 45 return 0; 46 }