HDU7149. Alice and Bob (2022杭电多校第1场L题)

HDU7149. Alice and Bob (2022杭电多校第1场L题)

题意

黑板上有若干个非负整数,其中非负整数 i 的数量为 ai

如果黑板上出现 0 这个数,Alice获胜,若没有进行下面的操作。

Alice首先将这若干个非负整数划分成两个部分(可以有一部分为空,但Alice这样一定会输)。

Bob根据Alice划的两部分,选择其中的一部分擦掉,将另一部分的所有整数减 1

操作完毕后,如果黑板上出现 0 这个数,Alice获胜,否则继续上述操作。

直到所有数都擦完,黑板上都没有出现过 0 这个数,Bob获胜。

假定Alice和Bob都以最优策略进行游戏,问谁会最终赢得游戏。

分析

对于Alice来说,0是唯一的不需要继续操作的必胜态的必要子集,我们可以尝试从0推出所有的必胜态的所有必要子集。

利用一个很显然的性质,如果Alice能做到划分出的两部分数都减掉1,这两部分数对于Alice来讲 都是 必胜态,则划分前的状态也是必胜态。

设一个集合 S,一开始 S=(0)。利用上面的性质进行逆推,两个 (0) 可以推出 (1,1),将这个元素加入到集合 S 中。

变成 S={(0),(1,1)}
(0)(1,1) 可以推出 (2,2,1)
两个 (1,1) 可以推出 (2,2,2,2)
将这两个元素加入到集合 S 中。

变成 S={(0),(1,1),(2,2,1),(2,2,2,2)}
(0)(2,2,1) 可以推出 (3,3,2,1)
(1,1)(2,2,1) 可以推出 (3,3,2,2,2)
两个 (2,2,1) 可以推出 (3,3,3,3,2,2)
(2,2,2,2)(0) 可以推出 (3,3,3,3,1)
(2,2,2,2)(1,1) 可以推出 (3,3,3,3,2,2)
(2,2,2,2)(2,2,1) 可以推出 (3,3,3,3,3,3,2)
(2,2,2,2)(2,2,2,2) 可以推出 (3,3,3,3,3,3,3,3)
将上面推出的 7 个元素加入到 S 中。

以此类推……。

推了这么多,很容易发现这个集合里元素的性质。概括且抽象地说,假如我们认为每两个 n,能合并成一个 n1,那么集合 S 中的元素一定可以最终合并成元素 (0)。反之,如果某个状态能够合并成状态 (0),那么这个状态一定在这个集合里面(这个“反之”可以想想为什么)。那么这个性质就可以完整描述这个集合了。并且,只要Alice遇到的状态中的某个子集在集合 S 当中,Alice就赢了。

于是,判断这道题谁赢的方法也很显然了,可以从大到小进行贪心,如果数 iai 个,那么数 i1 的个数(即 ai1)会增加 ai2 个。以此类推,最后判断 a0 是否大于 0,如果大于 0,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 中国大陆许可协议进行许可。

posted @   聆竹听风  阅读(271)  评论(0编辑  收藏  举报
历史上的今天:
2021-07-20 HDU 6955. Xor Sum题解
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起