$ \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: 取石子的更多相关文章

  1. BZOJ 3895: 取石子[SG函数 搜索]

    有N堆石子 ·从某堆石子中取走一个 ·合并任意两堆石子 不能操作的人输. 100%的数据满足T<=100,  N<=50. ai<=1000   容易发现基础操作数$d=\sum a ...

  2. bzoj 3895 取石子——博弈论

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看题解:https://blog.csdn.net/popoqqq/article/d ...

  3. bzoj 3895 取石子 —— 博弈论

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看了博客:https://blog.csdn.net/popoqqq/article/ ...

  4. bzoj 1874 取石子游戏 题解 &amp; SG函数初探

    [原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 334  Solved ...

  5. BZOJ 1874 取石子游戏 - SG函数

    Description $N$堆石子, $M$种取石子的方式, 最后取石子的人赢, 问先手是否必胜 $A_i <= 1000$,$ B_i <= 10$ Solution 由于数据很小, ...

  6. BZOJ 3895 3895: 取石子 / Luogu SP9934 ALICE - Alice and Bob (博弈 记忆化搜索)

    转自PoPoQQQ大佬博客 题目大意:给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 直接想很难搞,我们不妨来考虑一个特殊情况 假设每堆石子的数量都&g ...

  7. 【BZOJ】3895: 取石子

    [算法]博弈论+记忆化搜索 [题意]给定n堆石子,两人轮流操作,每个人可以合并两堆石子或拿走一个石子,不能操作者输,问是否先手必胜 [题解] 首先,若所有石子堆的石子数>1,显然总操作数为(石子 ...

  8. BZOJ 1413 取石子游戏(DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1413 题意:n堆石子排成一排.每次只能在两侧的两堆中选择一堆拿.至少拿一个.谁不能操作谁 ...

  9. BZOJ 1874 取石子游戏 (NIM游戏)

    题解:简单的NIM游戏,直接计算SG函数,至于找先手策略则按字典序异或掉,去除石子后再异或判断,若可行则直接输出. #include <cstdio> const int N=1005; ...

随机推荐

  1. C# web程序,winform程序,控制台程序配置log4net,使用log4net

    第一添加log4net.config,这里配置包括信息提示写入,错误信息写入,控制台消息展示 <?xml version="1.0" encoding="utf-8 ...

  2. webRTC peerconnection_client demo创建VS工程

    编译了webRTC Windows源码之后,想使用编译出来的库写一个demo出来,但是又不知到怎么下手.就想通过源码中带的示例peerconnection_client和peerconnection_ ...

  3. Ceph基本情况介绍

    Ceph基本情况的介绍 Ceph是一个分布式存储软件. 它支持用3种方式存储数据,分别是:对象存储.块设备存储.分布式文件系统存储. Ceph最初的目标是做一个分布式文件系统,直到现在这个目标也不能算 ...

  4. pom.xml配置指定仓库

    <repositories> <repository> <id>central</id><--中央仓库--> <url>http ...

  5. Java虚拟机(二):垃圾回收算法

    一.介绍 GC(Garbage Collection),垃圾收集 Java中,GC的对象是堆空间和永久区 二.GC算法 1. 引用计数法 老牌垃圾回收算法 通过引用计算来回收垃圾 Java中未使用,使 ...

  6. C# 文件打印

    Process pr = new Process();                     pr.StartInfo.FileName = “C:\test.xls”;               ...

  7. 图解KMP算法

  8. Docker学习笔记_安装和使用mysql

    一.系统环境和准备 1.宿主机OS:Win10 64位 2.虚拟机OS:Ubuntu18.04 3.操作账号:docker 二.安装 1.搜索mysql镜像:docker search mysql 2 ...

  9. Django--form基础

    一.Django--form功能 用户提交数据验证 生成html标签 二.基础实例 需求 利用Djang​o的form功能,接收用户注册信息. urls.py 1 2 3 4 5 from app01 ...

  10. 627D Preorder Test

    传送门 题目大意 给出一棵无根树,每个节点有一个权值,现在要让dfs序的前k个结点的最小值最大,求出这个值.分析 首先可以对这个值v进行二分然后01分数规划现在问题转化为求出一个dfs序,使得dfs序 ...