【题解】#10246. 「一本通 6.7 练习 3」取石子
Description
Sample Input
3
3
1 1 2
2
3 4
3
2 3 5
Sample Output
YES
NO
NO
Solution
我天,真神仙题!
这题其实是博弈论DP,一开始还想着直接用SG * 过去。
我们先从最简单的入手:
只有一堆石子时我们可以不考虑合并造成的影响那么一个人赢的情况只有可能是他剩下可以进行的操作数是奇数。
(这里我们发现剩下可以进行的操作数只有取一个石子)
那如果有两个堆。
(假设只有一个石子的堆叫做寂寞堆,大于一个石子的堆叫做热闹堆)
那么我们要分两种情况分别讨论:
\(1.\) 我们有两个堆,一个寂寞堆一个热闹堆。
那么我们假设寂寞堆 \(1\) 个石子,热闹堆 \(2\) 个石子,那么很明显我们当前只有要么从两个堆里取一个,要么合并。
首先考虑合并:合并之后热闹堆的奇偶性变了,同时合并之后取的是对手,这样就保证了对手赢。
考虑先把寂寞堆取完,那么我们在热闹堆中是可以直接根据奇偶求出谁会赢。如果先取热闹堆对手是有赢的策略的。
到这里我们发现好像寂寞堆会影响答案,如果只有热闹堆,热闹堆之间的合并不会改变他们的奇偶,对我们考虑没有影响,只会导致赢输的人不一样。
但如果出现了寂寞堆,寂寞堆的合并会影响热闹堆的奇偶性,所以要特殊考虑寂寞堆。
这个时候就要我们上博弈论DP了 然而我不知道为什么要上(逃
设状态 \(f[i][j]\) 表示有 \(i\) 个寂寞堆,\(j\) 次对于热闹堆的操作时当前操作的人是赢还是输。
这个状态好诡异
我们转移怎么办呢?
分类讨论一下:
\(1.\) 寂寞堆操作
- 寂寞堆取一个石子,很明显转移到 \(f[i-1][j]\)
- 寂寞堆合并(2个寂寞堆) 转移到 \(f[i-2][j+2]\)(合并之后多了一个热闹堆,要对热闹堆进行两次取石子操作),但突然发现如果还有热闹堆的话我们还会多一次合并操作,那就转移到 \(f[i-2][j+2+(j?1:0)]\)
- 寂寞堆合并到热闹堆上,转移到 \(f[i-1][j+1]\)
\(2.\) 热闹堆操作
- 从热闹堆里取一个石子,需要考虑是否取了之后变为寂寞堆。也就是 \(j\) 是否为 \(1\)。两个转移 \(f[i+1][0](j==1),f[i+1][j-1]\)
这样之后好像就没啥子了。注意一下细节就莫得了。
#include<bits/stdc++.h>
using namespace std;int T,n;
const int N=55,M=1005;
int a[N],f[N][M*N];inline int dfs(int num,int sum){if(num<=0 && sum<=0) return 0;if(f[num][sum]!=-1) return f[num][sum];if(num<=0) return f[num][sum]=(sum&1);if(sum==1) return f[num][sum]=dfs(num+1,0);f[num][sum]=0;if(num && !dfs(num-1,sum)) return f[num][sum]=1; // 拿一个寂寞堆的石子if(sum && !dfs(num,sum-1)) return f[num][sum]=1; // 把一个热闹堆里拿掉一个石子if(num && sum && !dfs(num-1,sum+1)) return f[num][sum]=1; // 把一个寂寞堆合并到热闹堆上if(num>1 && !dfs(num-2,sum+2+(sum?1:0))) return f[num][sum]=1; // 把两个寂寞堆合并return f[num][sum];
}int main(){scanf("%d",&T);memset(f,-1,sizeof(f));while(T--){int cnt=0,step=0;scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&a[i]);if(a[i]==1) cnt++;if(a[i]>1) step+=a[i]+1;}if(step) step--;printf("%s\n",dfs(cnt,step)?"YES":"NO"); }return 0;
}
转载于:https://www.cnblogs.com/JCNL666/p/10904187.html
【题解】#10246. 「一本通 6.7 练习 3」取石子相关推荐
- LibreOJ10082. 「一本通 3.3 例 1」Word Rings【二分+SPFA】
10082. 「一本通 3.3 例 1」Word Rings [题目描述] 传送门 [题解] 将一个字符串看成一条边,字符两端的字符看成节点,长度看成权值.二分枚举答案,最后SPFA刷正环,因为只要有 ...
- 「一本通 6.5 练习 3」迷路
「一本通 6.5 练习 3」迷路 题目描述 大意说一个给你有向图, 一个有n个节点,每个节点相连的边为所需要花费的时间, 问你从1到n 在时间刚好为t是的方案数.输出%2009 注意:不能在某个节点逗 ...
- 【C++】「一本通 1.1 例 4」加工生产调度
「一本通 1.1 例 4」加工生产调度 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据范围] [解析] [代码] [来源] 一本通题库-1425 LibreOJ ...
- #10016. 「一本通 1.2 练习 3」灯泡(三分)
参考博客链接:「一本通 1.2 练习 3」灯泡(三分) #include<stdio.h> #include<string.h> #include<math.h> ...
- 【C++】「一本通 1.1 例 2」种树
「一本通 1.1 例 2」种树 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [解析] [代码] [来源] 一本通题库-1423 LibreOJ-10001 vjud ...
- #10001. 「一本通 1.1 例 2」种树
#10001. 「一本通 1.1 例 2」种树 满足n个区间种树的要求,求最少种多少棵数 思路 按照区间的尾巴来排序,因为如果区间有重叠的种在第一个区间的尾巴可以使得种树更少,所有每次始从尾巴开始种树 ...
- 【C++】「一本通 1.1 例 5」智力大冲浪
「一本通 1.1 例 5」智力大冲浪 [来源] [题目描述] [输入格式] [输出格式] [输入样例] [输出样例] [数据范围] [解析] [代码] [来源] 一本通题库-1426 LibreOJ- ...
- #10172. 「一本通 5.4 练习 1」涂抹果酱 题解
题目链接 一道三进制状压的好题. 题目描述: Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕.蛋糕俯视图是一个 N×M的矩形,它被划分成 N×M个边长为 1×1的小正方形区域(可以把 ...
- 「一本通 1.2 例 2」Best Cow Fences
题目链接: 链接: [link](信息学奥赛一本通(C++版)在线评测系统). 首先这道题要求找平均数,且要求所选片段长度需要大于等于l.那么首先想到的就是最暴力的方法就是找到所有大于等于l的片段在其 ...
- LOJ #10222. 「一本通 6.5 例 4」佳佳的 Fibonacci
题目链接 题目大意 $$F[i]=F[i-1]+F[i-2]\ (\ F[1]=1\ ,\ F[2]=1\ )$$ $$T[i]=F[1]+2F[2]+3F[3]+...+nF[n]$$ 求$T[n] ...
最新文章
- 科普大V河森堡:用科学的方法回答哲学问题
- 解决ARC下performselector-may-cause-a-leak-because-its-selector-is-unknown 警告
- OpenCV基本mat重建的实例(附完整代码)
- Lucene学习总结之三:Lucene的索引文件格式(2)
- 网站QQ全屏PHP代码,QQ技术导航升级版 超级导航美化版带后台版 PHP源码
- torch.randn与torch.rand的区别
- webStorm关闭自动保存
- Vscode linux ubuntu deb 最新下载
- Oracle数据库merge into的使用,存在则更新,不存在则插入
- 【各学校通用】5分钟刷完天津科技大学雨课堂视频
- PHP Smarty 学习手册
- 课设(房屋出租系统)
- 2022年中国工业机器人市场现状研究分析与发展前景预测报告
- 算法思考题-三只老鼠找8瓶毒药思路(个人思考+收集)
- 一个关于家具的横幅广告
- D2大会资源分享(解决了GitHub下载限速)
- 大数据系统搭建(一)基础配置
- OpenCV for Python之图像RIO与泛洪填充
- Android开发音效增强中铃声播放Ringtone及声音池调度SoundPool的讲解及实战(超详细 附源码)
- Linux下二进制文件的查看和编辑