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

Sample Output

0

数据范围
对于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 }
原文地址:https://www.cnblogs.com/wfj2048/p/8012440.html