P2599 [ZJOI2009]取石子游戏 做题感想
前言
发现自己三岁时的题目都不会做。
我发现我真的是菜得真实。
正文
神仙构造,分讨题。
不敢说有构造,但是分讨我只服这道题。
看上去像是一个类似 \(Nim\) 游戏的变种,经过不断猜测结论无果后果断弃疗。
(然后我就出门右转直接进了题解区),在这里记录一下自己的理解。
设 \(l_{i,j}\) 表示在 \(i\sim j\) 这个区间左边再加一堆 \(l_{i,j}\) 的石子时,先手必败。
同理,设 \(r_{i,j}\) 表示在 \(i\sim j\) 这个区间右边再加一堆 \(r_{i,j}\) 的石子时,先手必败。
(以下的所有证明以及验证我们都以 \(l_{i,j}\) 为准,\(r_{i,j}\) 情况相同)。
等等,如果上述满足条件的石子个数不唯一,怎么办?
好像不太好搞欸,是不是要再开一维数组?
既然不唯一的情况这么困难,为什么不想想会不会存在这种情况呢?
证明:
我们假设 \(l_{i,j}\) 存在两种可能 \(a\) 和 \(b\) ,且我们钦定 \(a < b\)。
既然 \(a\) 和 \(b\) 都满足要求,所以此时都是必败态。
但是很显然,我们可以让先手对于 \(b\) 的情况一直取直到 \(a\) 。
此时先手让后手到了一个必败态所以先手必败。??(对,这就是不唯一时的推理)
所以可以得出,\(l_{i,j}\) 一定是唯一的。
那万一 \(l_{i,j}\) 不存在怎么办?
等一等,\(l_{i,j}\) 是不是一定存在呢?
在这里我口胡一下:
因为对于所有的 \([i,j]\) 区间都不存在 \(l_{i,j}\) ,则对于所有从左边拿的一定是必胜态。
但是如果只有一堆石子 \(a\) 的话:此时可以发现 \(l_{i,j} = a\) 因为此时先手怎么取后手也学者他。
这样的话后手会取完最后一个石子。
所以,\(l_{i,j}\) 一定是存在的的。
现在来进行刺激的分讨过程。
我在这里会对每一种可能的结果进行简要的说明。
- 首先我们先来考虑边界的情况:
就和我之前说的一样 \(l_{i,i} = a_i\) , \(r_{i,i}\) 同理。
为了方便起见,我们令 \(x=a_j\) , \(L =l_{i,j-1}\) , \(R=r_{i,j-1}\) 。
- ( \(x < L\) 且 \(x <R\) ) 或者 ( \(x > L\) 且 \(x >R\) )
\(l_{i,j} = x\) 。
此时我们可以运用类似之前的方法,先手取什么,后手就取什么。
那么最后的结果就是先手先取完了左右两端石子中的一堆。
然后后手可以随便取另一边的一堆,使得此堆的数量变成 \(l_{i,j}\) 或 \(r_{i,j}\) 。
- \(R<x<L\)
\(L_{i,j} = x-1\)
假设先手先拿了左边这一堆。
那么假设还剩下了 \(x\) 个石子,如果 \(x<R\),后手把右侧的那一堆也给拿成 \(x\) 就成了( \(x < L\) 且 \(x <R\) )这种情况。
如果 \(x\geq R\),那么后手把最后那一堆拿成 \(x+1\),于是又回到了我们讨论的这种情况。
同理,我们也可以推出右边先取玩的的情况。
- \(L<x<R\)
\(L_{i,j} = x+1\)
和上一种基本上是一摸一样,在这里就不讲了。
Code
#include <bits/stdc++.h>
#define file(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define Enter puchar('\n')
#define quad putchar(' ')
const int N = 1005;
int T, a[N], l[N][N], r[N][N];
signed main(void) {
// file("P2599");
std::cin >> T;
for (int test = 1, n; test <= T; test++) {
std::cin >> n;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
l[i][i] = r[i][i] = a[i];
for (int len = 1; len <= n; len ++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
int L, R, x;
x = a[j];
L = l[i][j - 1]; R = r[i][j - 1];
if (R == x) l[i][j] = 0;
else if (x < L && x < R) l[i][j] = x;
else if (x > L && x > R) l[i][j] = x;
else if (R < x && x < L) l[i][j] = x - 1;
else l[i][j] = x + 1;
x = a[i];
L = l[i + 1][j]; R = r[i + 1][j];
if (L == x) r[i][j] = 0;
else if (x < L && x < R) r[i][j] = x;
else if (x > L && x > R) r[i][j] = x;
else if (R < x && x < L) r[i][j] = x + 1;
else r[i][j] = x - 1;
}
}
if (l[2][n] == a[1]) std::cout << "0" << std::endl;
else std::cout << "1" << std::endl;
}
}
P2599 [ZJOI2009]取石子游戏 做题感想的更多相关文章
- 【BZOJ1413】[ZJOI2009]取石子游戏(博弈论,动态规划)
[BZOJ1413][ZJOI2009]取石子游戏(博弈论,动态规划) 题面 BZOJ 洛谷 题解 神仙题.jpg.\(ZJOI\)是真的神仙. 发现\(SG\)函数等东西完全找不到规律,无奈只能翻题 ...
- bzoj 1413 [ZJOI2009]取石子游戏
1413: [ZJOI2009]取石子游戏 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 747 Solved: 490[Submit][Statu ...
- 【一本通提高博弈论】[ZJOI2009]取石子游戏
[ZJOI2009]取石子游戏 题目描述 在研究过 Nim 游戏及各种变种之后,Orez 又发现了一种全新的取石子游戏,这个游戏是这样的: 有 n n n 堆石子,将这 n n n 堆石子摆成一排.游 ...
- 【刷题】BZOJ 1413 [ZJOI2009]取石子游戏
Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...
- vijos 1557:bzoj:1413: [ZJOI2009]取石子游戏
Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...
- bzoj1413 [ZJOI2009]取石子游戏
Description 在研究过Nim游戏及各种变种之后,Orez又发现了一种全新的取石子游戏,这个游戏是这样的: 有n堆石子,将这n堆石子摆成一排.游戏由两个人进行,两人轮流操作,每次操作者都可以从 ...
- 洛谷P2599||bzoj1413 [ZJOI2009]取石子游戏
bzoj1413 洛谷P2599 根本不会啊... 看题解吧 #include<cstdio> #include<algorithm> #include<cstring& ...
- [ZJOI2009]取石子游戏
瞪了题解两三天,直接下转第二篇题解就康懂了 首先我们令 : \(L[i][j]\) 表示当前 \([i,j]\) 区间左侧放置 \(L[i,j]\) 数量的石子后先手必败 \(R[i][j]\) 表示 ...
- Games:取石子游戏(POJ 1067)
取石子游戏 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 37662 Accepted: 12594 Descripti ...
随机推荐
- jointJS初使用随记
jointJs使用随记 1.下载与安装 前提:一个健康良好且干净的vue脚手架项目. 还是普遍的安装方式 yarn:yarn add jointjs npm:npm install jointjs 还 ...
- OpenHarmony 3.1 Beta版本关键特性解析——分布式DeviceProfile
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 成翔 OpenAtom OpenHarmony(以下简称"OpenHarmony")作为分布式操作 ...
- WPF样式和触发器
理解样式 样式可以定义通用的格式化特征集合. Style 类的属性 Setters.Triggers.Resources.BasedOn.TargetType <Style x:Key=&quo ...
- 单列集合(Collection-List)
与数组的区别 ArrayList while循环快捷键itit 遍历方法2:增强for循环 快捷键大写的I List接口(少部分常用的) List三种遍历方式 注意事项 ArrrayList底层结构和 ...
- Django学习——Django测试环境搭建、单表查询关键字、神奇的双下划线查询(范围查询)、图书管理系统表设计、外键字段操作、跨表查询理论、基于对象的跨表查询、基于双下划线的跨表查询
Django测试环境搭建 ps: 1.pycharm连接数据库都需要提前下载对应的驱动 2.自带的sqlite3对日期格式数据不敏感 如果后续业务需要使用日期辅助筛选数据那么不推荐使用sqlite3 ...
- 定时 ——setTimeout | setInterval
使用场景,setTimeout 只调用一次,setInterval 会重复调用,直到清除或重载. <div id="countDown"></div> &l ...
- linux下虚拟环境venv的创建与使用以及virtualenvwrapper
1.linux安装学习python虚拟环境 linux提供的虚拟环境工具 有virtualenv pipenv 2.我们需求是在linux上可以运行 一个django2 运行一个django1 3.安 ...
- 使用C#跨PC 远程调用程序并显示UI界面
在项目中有一个需求是需要在局域网内跨PC远程调用一个程序,并且要求有界面显示,调查了一些资料,能实现远程调用的.Net技术大概有PsExec.WMI.Schedule Task. 这三种方式都做了一个 ...
- 万字长文深度剖析 RocketMQ 设计原理
幸福的烦恼 张大胖最近是又喜又忧,喜的是业务量发展猛增,忧的是由于业务量猛增,一些原来不是问题的问题变成了大问题,比如说新会员注册吧,原来注册成功只要发个短信就行了,但随着业务的发展,现在注册成功也需 ...
- Redis设计与实现3.3:集群
集群 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 集群中的节点 创建集群 通过 CLUSTER NODE 命令可以查看当前集群中的节点.刚启动时,默认每一台 ...