HDU7149. Alice and Bob (2022杭电多校第1场L题)
HDU7149. Alice and Bob (2022杭电多校第1场L题)
题意
黑板上有若干个非负整数,其中非负整数 的数量为 。
如果黑板上出现 这个数,Alice获胜,若没有进行下面的操作。
Alice首先将这若干个非负整数划分成两个部分(可以有一部分为空,但Alice这样一定会输)。
Bob根据Alice划的两部分,选择其中的一部分擦掉,将另一部分的所有整数减 。
操作完毕后,如果黑板上出现 这个数,Alice获胜,否则继续上述操作。
直到所有数都擦完,黑板上都没有出现过 这个数,Bob获胜。
假定Alice和Bob都以最优策略进行游戏,问谁会最终赢得游戏。
分析
对于Alice来说,0是唯一的不需要继续操作的必胜态的必要子集,我们可以尝试从0推出所有的必胜态的所有必要子集。
利用一个很显然的性质,如果Alice能做到划分出的两部分数都减掉1,这两部分数对于Alice来讲 都是 必胜态,则划分前的状态也是必胜态。
设一个集合 ,一开始 。利用上面的性质进行逆推,两个 可以推出 ,将这个元素加入到集合 中。
变成 。
和 可以推出 ;
两个 可以推出 ;
将这两个元素加入到集合 中。
变成 。
和 可以推出 ;
和 可以推出 ;
两个 可以推出 ;
和 可以推出 ;
和 可以推出 ;
和 可以推出 ;
和 可以推出 ;
将上面推出的 个元素加入到 中。
以此类推……。
推了这么多,很容易发现这个集合里元素的性质。概括且抽象地说,假如我们认为每两个 ,能合并成一个 ,那么集合 中的元素一定可以最终合并成元素 。反之,如果某个状态能够合并成状态 ,那么这个状态一定在这个集合里面(这个“反之”可以想想为什么)。那么这个性质就可以完整描述这个集合了。并且,只要Alice遇到的状态中的某个子集在集合 当中,Alice就赢了。
于是,判断这道题谁赢的方法也很显然了,可以从大到小进行贪心,如果数 有 个,那么数 的个数(即 )会增加 个。以此类推,最后判断 是否大于 ,如果大于 ,Alice赢,否则Bob赢。
代码
#include <iostream> using namespace std; const int maxn = 1e6 + 10; int n; int num[maxn]; void solve() { cin >> n; for (int i = 0; i <= n; i++) { cin >> num[i]; } for (int i = n; i >= 1; i--) { num[i - 1] += (num[i] >> 1); } if (num[0] > 0) { cout << "Alice\n"; } else { cout << "Bob\n"; } } int main() { ios::sync_with_stdio(0); cin.tie(0); int T; cin >> T; while (T--) { solve(); } return 0; }
本文作者:聆竹听风
本文链接:https://www.cnblogs.com/Bamboo-Wind/p/16498115.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-07-20 HDU 6955. Xor Sum题解