瞪了题解两三天,直接下转第二篇题解就康懂了

首先我们令 :

\(L[i][j]\) 表示当前 \([i,j]\) 区间左侧放置 \(L[i,j]\) 数量的石子后先手必败

\(R[i][j]\) 表示当前 \([i,j]\) 区间右侧放置 \(R[i,j]\) 数量的石子后先手必败

那么最后我们只要判断 \(a[1]\) 是否等于 \(L[2,n]\) 或者 \(a[n]\) 是否等于 \(R[1,n-1]\) 即可

唯一性

考虑证明 \(L[i][j]\) 和 \(R[i][j]\) 的唯一性,发现我们只需要证明一个成立即可

假设 \(L[i][j]\) 存在两个,那么我们先让 \([i,j]\) 左边放上大的 \(L[i][j]\) ,那么它可以一步转移到另一个小的 \(L[i][j]\) ,仍旧是一个必败态,与定义矛盾,故 \(L[i][j]\) 只存在一个合法值

转移

然后我们分类讨论...

假设当前处理到了 \(L[i][j]\) ,那么我们根据 \(L[i][j-1] ,R[i][j-1] ,a[j]\) 来处理,我们令 \(L=L[i][j-1],R=R[i][j-1],x=a[j]\)

  1. \(x=R\)

    这种情况下,我们令 \(L[i][j]=0\) ,因为 [i,j] 已经是个必败态了,左边加上任意石子,先手都可以全部取完,然后后手面对必败态

  2. \(x<L,x<R\)

    这种情况下,我们令 \(L[i][j]=x\) ,这样先手不管从哪堆开始取,如果没有取完,后手只需要在另一堆取走相同数量的石子,就回到了原来的情况,那么如果说先手把一堆取完了,另一堆的石子数量必然是小于 L 和 R 的,相当于是先手从数量为 L 或者 R 的堆中取走了一些石子,后手必胜

  3. \(L<=x<R\)

    这种情况下,我们令 \(L[i][j]=x+1\) ,这样先手左边取左边取,取到 L 时,后手取光右边即可;左边取到比 L 大的话,右边只要取走相同的石子就好了,这样可以变回同样的状态;取到比 L 小的话,右边取到相同的石子数为止,这样两边的石子数都小于 L 和 R ,这样就回到了状态 2 ;如果先手在右边取,如果取到比 L 大,我们维持状态即可,和上面一样;如果比 L 小,那么我们左边取到和左边相等,这样还是回到了状态 2 ;如果右边被先手取光了,那么我们把左边取到 L ,先手面临的就是必败态了

  4. \(R<x<L\)

    这种情况下,我们令 \(L[i][j]=x-1\) 即可,讲道理是和状态 3 差不多的情况 Q^Q

  5. \([i,i]\) 的边界情况

    我们只需要让 \(L[i][i]=a[i]\) 即可...因为左边放上 a[i] 就是先手必败的状态,考虑此时无论先手在哪里取,后手只要在另一堆里面取相同石子即可...

感谢

ORZ YYB

Code

//by Judge
#include<bits/stdc++.h>
#define Rg register
#define fp(i,a,b) for(Rg int i=(a),I=(b)+1;i<I;++i)
#define ll long long
using namespace std;
const int M=1003;
typedef int arr[M][M];
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline ll read(){ ll x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21];int CC=-1;
inline void Ot(){fwrite(sr,1,CC+1,stdout),CC=-1;}
int n,a[M]; arr L,R;
int main(){ int T=read();
while(T--){ n=read();
fp(i,1,n) L[i][i]=R[i][i]=a[i]=read();
fp(len,1,n-2) fp(i,2,n-len){
Rg int j=i+len;
if(R[i][j-1]==a[j]) L[i][j]=0;
else if(L[i][j-1]>a[j]&&R[i][j-1]>a[j]) L[i][j]=a[j];
else if(L[i][j-1]<=a[j]&&R[i][j-1]>a[j]) L[i][j]=a[j]+1;
else if(L[i][j-1]>a[j]&&R[i][j-1]<a[j]) L[i][j]=a[j]-1;
else L[i][j]=a[j];
if(R[i+1][j]==a[i]) R[i][j]=0;
else if(L[i+1][j]>a[i]&&R[i+1][j]>a[j]) R[i][j]=a[i];
else if(L[i+1][j]<=a[i]&&R[i+1][j]>a[j]) R[i][j]=a[i]+1;
else if(L[i+1][j]>a[i]&&R[i+1][j]<a[j]) R[i][j]=a[i]-1;
else R[i][j]=a[i];
}
sr[++CC]=48+(a[1]!=L[2][n]),sr[++CC]='\n';
}
return Ot(),0;
}

[ZJOI2009]取石子游戏的更多相关文章

  1. 【BZOJ1413】[ZJOI2009]取石子游戏(博弈论,动态规划)

    [BZOJ1413][ZJOI2009]取石子游戏(博弈论,动态规划) 题面 BZOJ 洛谷 题解 神仙题.jpg.\(ZJOI\)是真的神仙. 发现\(SG\)函数等东西完全找不到规律,无奈只能翻题 ...

  2. bzoj 1413 [ZJOI2009]取石子游戏

    1413: [ZJOI2009]取石子游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 747  Solved: 490[Submit][Statu ...

  3. 【一本通提高博弈论】[ZJOI2009]取石子游戏

    [ZJOI2009]取石子游戏 题目描述 在研究过 Nim 游戏及各种变种之后,Orez 又发现了一种全新的取石子游戏,这个游戏是这样的: 有 n n n 堆石子,将这 n n n 堆石子摆成一排.游 ...

  4. vijos 1557:bzoj:1413: [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  5. 【刷题】BZOJ 1413 [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  6. bzoj1413 [ZJOI2009]取石子游戏

    Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...

  7. P2599 [ZJOI2009]取石子游戏 做题感想

    题目链接 前言 发现自己三岁时的题目都不会做. 我发现我真的是菜得真实. 正文 神仙构造,分讨题. 不敢说有构造,但是分讨我只服这道题. 看上去像是一个类似 \(Nim\) 游戏的变种,经过不断猜测结 ...

  8. 洛谷P2599||bzoj1413 [ZJOI2009]取石子游戏

    bzoj1413 洛谷P2599 根本不会啊... 看题解吧 #include<cstdio> #include<algorithm> #include<cstring& ...

  9. Games:取石子游戏(POJ 1067)

    取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37662   Accepted: 12594 Descripti ...

随机推荐

  1. Mysql数据库表类型

    MySQL的数据表类型很多,其中比较重要的是MyISAM,InnoDB这两种. 这两种类型各有优缺点,需要根据实际情况选择适合的,MySQL支持对不同的表设置不同的类型.下面做个对比:   MyISA ...

  2. Java大文件上传详解及实例代码

    1,项目调研 因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 在GoogleCode上面,代码弄下来超级不方便,还是配置hosts才好,把代码重新上传到了github上面. http ...

  3. 对拍程序 x

    一.介绍 在做题或者正式比赛过程中总会把水题做水做乱,但因为样例有坑所以直接过了样例,然后拿去评测结果发现全WA.那如何在这种情况下检查自己程序或算法的正确性呢?对拍是一个简便省事的方案. 所谓“对拍 ...

  4. Dmango cxrf 自定义分页 缓存 session 序列化 信号量 知识点

    参考https://www.cnblogs.com/wupeiqi/articles/5246483.html

  5. String、StringBuffer与StringBuilder介绍

    关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺点,到底什么时候该用谁呢?下面我们从以下几点说明一下 1.三者在执行速度方面的比较:     StringBuilder > St ...

  6. [ethereum源码分析](1) dubug环境搭建

    前言 因为最近云小哥哥换了一份工作,新公司比较忙,所以一直没有更新新的博客.云小哥哥新的公司是做区块链的,最近在学习区块链相关的东西(也算是乘坐上了区块链这艘大船).本博客是记录我搭建ethereum ...

  7. js 在输出到页面的5中方式

    1.alert("要输出的内容"); ->在浏览器中弹出一个对话框,然后把要输出的内容展示出来 ->alert都是把要输出的内容首先转换为字符串然后在输出的 2.doc ...

  8. 大数据笔记(二十一)——NoSQL数据库之Redis

    一.Redis内存数据库 一个key-value存储系统,支持存储的value包括string(字符串).list(链表).set(集合).zset(sorted set--有序集合)和hash(哈希 ...

  9. HTTP入门(二):用Chrome开发者工具查看 HTTP 请求与响应

    HTTP入门(二):用Chrome开发者工具查看 HTTP 请求与响应 本文简单总结HTTP的请求与响应. 本文主要目的是对学习内容进行总结以及方便日后查阅. 详细教程和原理可以参考HTTP文档(MD ...

  10. 字节对齐#pragma pack

    这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对 ...