bzoj 3895: 取石子
$ \color{#0066ff}{ 题目描述 }$
Alice和Bob两个好朋含友又开始玩取石子了。游戏开始时,有N堆石子
排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个:
·从某堆石子中取走一个
·合并任意两堆石子
不能操作的人输。Alice想知道,她是否能有必胜策略。
\(\color{#0066ff}{输入格式}\)
第一行输入T,表示数据组数。
对于每组测试数据,第一行读入N。
接下来N个正整数a1,a2…an,表示每堆石子的数量。
\(\color{#0066ff}{输出格式}\)
对于每组测试数据,输出一行。
输出YES表示Alice有必胜策略,输出NO表示Alice没有必胜策略。
\(\color{#0066ff}{输入样例}\)
3
3
1 1 2
2
3 4
3
2 3 5
\(\color{#0066ff}{输出样例}\)
YES
NO
NO
\(\color{#0066ff}{数据范围与提示}\)
100%的数据满足T<=100, N<=50. ai<=1000
\(\color{#0066ff}{题解}\)
如果合并,石子数不变,如果取,石子数-1,表面上看,结局已经注定,跟操作数的奇偶有关
然而,会有这样的情况,比如1和1
合并,那么操作数-1,如果取走一个1,那么操作数-2!!!这是不一样的
于是我们发现,状态实际上只跟1的堆数和操作数有关
所以,设\(sg[x][y]\)表示当前有x堆是1,除了1的那些堆的操作数共y次的SG值
然后分别讨论所有情况进行转移
因为不涉及多个游戏的合并,所以sg不是0就是1,就不用开vis数组记录什么东西了
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
int n;
int sg[55][52050];
int work(int x, int y) {
if(!x) return y & 1;
if(y == 1) return sg[x][y] = work(x + 1, y - 1);
if(~sg[x][y]) return sg[x][y];
if(x && !work(x - 1, y)) return sg[x][y] = 1;
if(x && y && !work(x - 1, y + 1)) return sg[x][y] = 1;
if(x >= 2 && !work(x - 2, y + 2 + (y > 0))) return sg[x][y] = 1;
if(y && !work(x, y - 1)) return sg[x][y] = 1;
//拿走一个1
//1跟非1合并
//两个1合并
//某个非1堆拿走1个或合并两个非1堆
return sg[x][y] = 0;
}
int main() {
memset(sg, -1, sizeof sg);
for(int T = in(); T --> 0;) {
n = in();
int x = 0, y = 0, z;
for(int i = 1; i <= n; i++) {
z = in();
x += (z == 1);
y += (z > 1) * z;
}
y += n - x - 1;
if(y == -1) y++;
printf(!work(x, y)? "NO\n" : "YES\n");
}
return 0;
}
bzoj 3895: 取石子的更多相关文章
- BZOJ 3895: 取石子[SG函数 搜索]
有N堆石子 ·从某堆石子中取走一个 ·合并任意两堆石子 不能操作的人输. 100%的数据满足T<=100, N<=50. ai<=1000 容易发现基础操作数$d=\sum a ...
- bzoj 3895 取石子——博弈论
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看题解:https://blog.csdn.net/popoqqq/article/d ...
- bzoj 3895 取石子 —— 博弈论
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看了博客:https://blog.csdn.net/popoqqq/article/ ...
- bzoj 1874 取石子游戏 题解 & SG函数初探
[原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 334 Solved ...
- BZOJ 1874 取石子游戏 - SG函数
Description $N$堆石子, $M$种取石子的方式, 最后取石子的人赢, 问先手是否必胜 $A_i <= 1000$,$ B_i <= 10$ Solution 由于数据很小, ...
- BZOJ 3895 3895: 取石子 / Luogu SP9934 ALICE - Alice and Bob (博弈 记忆化搜索)
转自PoPoQQQ大佬博客 题目大意:给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 直接想很难搞,我们不妨来考虑一个特殊情况 假设每堆石子的数量都&g ...
- 【BZOJ】3895: 取石子
[算法]博弈论+记忆化搜索 [题意]给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 [题解] 首先,若所有石子堆的石子数>1,显然总操作数为(石子 ...
- BZOJ 1413 取石子游戏(DP)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1413 题意:n堆石子排成一排.每次只能在两侧的两堆中选择一堆拿.至少拿一个.谁不能操作谁 ...
- BZOJ 1874 取石子游戏 (NIM游戏)
题解:简单的NIM游戏,直接计算SG函数,至于找先手策略则按字典序异或掉,去除石子后再异或判断,若可行则直接输出. #include <cstdio> const int N=1005; ...
随机推荐
- TableView被Navigation bar挡住的解决办法
在存在遮挡的ViewController的ViewDidload函数里添加以下两句即可解决 self.edgesForExtendedLayout = UIRectEdge.None self.aut ...
- c++builder Active Form
新增的属性.方法刷新一下才可以生成方法的实现.保存按钮不生成,刷新就好了. Refresh Implemention
- PHP数据结构之二 线性表中的顺序表的PHP实现
线性表 (一)基本特点:最基本.最简单.最常用的一种数据结构 在这种结构中: 1.存在一个唯一的被称为“第一个”的数据元素: 2.存在一个唯一的被称为“最后一个”的数据元素: 3.除第一个元素外,每个 ...
- Subscript & Inheritance
[Subscript] 1.subscript的定义: 2.Subscript的使用: 3.可以定义多维subscript: 多维Subscript的使用: [Inheritance] 1.overr ...
- laravel中间键组
` php artisan make:middleware Lend这边我定义一个登陆的中间件这边要注意的就是,当条件成立的时候一定要 return $next($request);不写这个larav ...
- axure可用密钥
axure8.0注册码 激活码:(亲测可用) 用户名:aaa 注册码:2GQrt5XHYY7SBK/4b22Gm4Dh8alaR0/0k3gEN5h7FkVPIn8oG3uphlOeytIajxG ...
- SpringBoot22 Ajax跨域、SpringBoot返回JSONP、CSRF、CORS
1 扫盲知识 1.1 Ajax为什么存在跨域问题 因为浏览器处于安全性的考虑不允许JS执行跨域请求. 1.2 浏览器为什么要限制JS的跨域访问 如果浏览器允许JS的跨域请求就很容易造成 CSRF (C ...
- 虚拟机Ubuntu16.04安装lrzsz
[系统环境] 宿主机:Win7 64位 虚拟机软件:Vmware workstation 12 虚拟机:Ubuntu 16.0.4 [目的] 配合Secure CRT使用rz,sz,方便在Ubuntu ...
- 算法Sedgewick第四版-第3章Searching-搜索总结
- 卡2-SLAM
---恢复内容开始--- 1.下载 首先需要从github上Git以下两个包: git clonehttps://github.com/ros-perception/open_karto(开源的kar ...