题目链接

前言

发现自己三岁时的题目都不会做。

我发现我真的是菜得真实。

正文

神仙构造,分讨题。

不敢说有构造,但是分讨我只服这道题。

看上去像是一个类似 \(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]取石子游戏 做题感想的更多相关文章

  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. 【刷题】BZOJ 1413 [ZJOI2009]取石子游戏

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

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

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

  6. bzoj1413 [ZJOI2009]取石子游戏

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

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

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

  8. [ZJOI2009]取石子游戏

    瞪了题解两三天,直接下转第二篇题解就康懂了 首先我们令 : \(L[i][j]\) 表示当前 \([i,j]\) 区间左侧放置 \(L[i,j]\) 数量的石子后先手必败 \(R[i][j]\) 表示 ...

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

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

随机推荐

  1. 【Vue3+Express实战】项目开发环境搭建

    大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...

  2. Docker极简入门:使用Docker-Compose 运行网站浏览量统计Demo

    Docker-Compose 是一个可以对 Docker 容器集群的快速编排的工具,能够减轻您心智和手指的负担. 简单的来说 Docker-Compose 就是将你运行多个容器的命令编写到了一起,类似 ...

  3. SpringBoot--Easycode、mybatisX插件生成entity,controller,service,dao,mapper IDEA版 项目提效神器

    一.介绍 Easycode是idea的一个插件,可以直接对数据的表生成entity,controller,service,dao,mapper,无需任何编码,简单而强大. MybatisX 是一款基于 ...

  4. 从同步函数 hello-world-dotnet 开始探索OpenFunction

    OpenFunction[1] 是一个现代化的云原生 FaaS(函数即服务)框架,它引入了很多非常优秀的开源技术栈,包括 Knative.Tekton.Shipwright.Dapr.KEDA 等,这 ...

  5. Nacos在企业生产中如何使用集群环境?

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 由于在公司,注册中心和配置中心都是 ...

  6. 分布式存储之GlusterFS

    公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 1.glusterfs概述 GlusterFS系统是一个可扩展的网络文件系统,相比其他分布式文件系统,GlusterFS具有 ...

  7. 【原创】记一次对X呼APP的渗透测试

    获取CMS并本地安装 X呼是一款开源的客服CMS系统,访问官网,下载安卓版本的app和源码本地搭建: 发现这cms预留admin表中的用户就不少.... 直接用预留的密码解密,然后就能登录手机APP了 ...

  8. Java 对象头那点事

    概览 对象头 存放:关于堆对象的布局.类型.GC状态.同步状态和标识哈希码的基本信息.Java对象和vm内部对象都有一个共同的对象头格式. (后面做详细介绍) 实例数据 存放:类的数据信息,父类的信息 ...

  9. DOM 事件与事件委托

    DOM 事件与事件委托 本文写于 2020 年 5 月 28 日 先思考一个问题:我们如何给一百个 button 添加点击事件? 遍历? 那岂不是要添加一百个监听器? 这就需要事件委托了. 其实这根本 ...

  10. c++动态内存分配需要注意的地方,可以不用尽量不用

    在实际开发中,需要动态分配内存的场景极少,string和vector已经足够方便,如果不是非用不可的情况,采用动态分配内存就是给自己挖坑. 如果应用开发中一定要用动态内存分配技术,建议把它封装在类中, ...