题解 | #1002.Random Nim Game# 2023杭电暑期多校7

1002.Random Nim Game

诈骗博弈题

题目大意

Nim是一种双人数学策略游戏,玩家轮流从不同的堆中移除棋子。在每一轮游戏中,玩家必须至少取出一个棋子,并且可以取出任意数量的棋子,条件是这些棋子都来自同一个棋子堆。走最后一步棋(即取出最后一块棋子)的人获胜。

现在更改游戏规则,在每个回合中,棋手必须选择一个棋子堆。假设他选择的堆包含 x x x 个棋子,将从 [ 1 , x ] [1,x] [1,x] 中随机一个整数 y y y ,并从堆中移除 y y y 个棋子

求先手获胜的概率,答案取模

解题思路

看起来很吓人的一道题(谁被吓退了我不说)//

考虑只有一个堆的情况

若只有 1 1 1 个棋子,先手必胜

如果有 2 2 2 个棋子,有 1 2 \dfrac{1}{2} 21 的概率拿完获胜,有 1 2 \dfrac{1}{2} 21 的概率余 1 1 1 失败,综合胜率 1 2 \dfrac{1}{2} 21
⋮ \vdots ⋮

如果有 x ( x > 1 ) x\ (x>1) x (x>1) 个棋子,有 n − 2 n \dfrac{n-2}{n} nn−2 的概率转移到 剩余个数 > 1 >1 >1 的状态,有 1 n \dfrac{1}{n} n1 的概率拿完获胜,有 1 n \dfrac{1}{n} n1 的概率余 1 1 1 失败。递归得到 x > 1 x>1 x>1 的状态下的综合胜率为 1 2 \dfrac{1}{2} 21

再考虑多堆的情况

如果所有堆的棋子数量均为 1 1 1 ,则当堆数 n n n 为奇数时先手必胜

如果有某堆的数量多于 1 1 1 个,那么必胜态将以 1 2 \dfrac{1}{2} 21 的概率流转

综上所述,如果所有堆的棋子数量均为 1 1 1 ,则当堆数 n n n 为奇数时先手必胜, n n n 为偶数时先手必败,其余情况综合胜率 1 2 \dfrac{1}{2} 21

参考代码

参考代码为已AC代码主干,其中部分功能需读者自行实现

cpp{.line-numbers} 复制代码
void solve()
{
    ll n;cin >> n;ll mx=0,t;
    FORLL(i,1,n){
        cin >> t;
        mx=max(mx,t);
    }if(mx>1) cout << inv(2) << endl;
    else if(n%2) cout << 1 << endl;
    else cout << 0 << endl;
}
相关推荐
肆忆_23 分钟前
实战复盘:手写 C++ 虚拟机的高性能并行 GC (Thread Pool + Work Stealing)
c++
肆忆_27 分钟前
虚函数进阶答疑:把上一篇博客评论区里最容易卡住的问题,一次追到底
c++
saltymilk17 小时前
使用 C++ 模拟 ShaderLanguage 的 swizzle
c++·模板元编程
xlp666hub1 天前
Leetcode第五题:用C++解决盛最多水的容器问题
linux·c++·leetcode
得物技术1 天前
搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术
c++·后端·测试
xlp666hub2 天前
Leetcode 第三题:用C++解决最长连续序列
c++·leetcode
会员源码网2 天前
构造函数抛出异常:C++对象部分初始化的陷阱与应对策略
c++
xlp666hub2 天前
Leetcode第二题:用 C++ 解决字母异位词分组
c++·leetcode
不想写代码的星星2 天前
static 关键字:从 C 到 C++,一篇文章彻底搞懂它的“七十二变”
c++
xlp666hub3 天前
Leetcode第一题:用C++解决两数之和问题
c++·leetcode