news 2026/5/26 23:36:01

P16288 [蓝桥杯 2026 省 Python/Java A 组] 魔法骰子 题解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P16288 [蓝桥杯 2026 省 Python/Java A 组] 魔法骰子 题解

P16288 [蓝桥杯 2026 省 Python/Java A 组] 魔法骰子

Link: https://www.luogu.com.cn/problem/P16288

题目描述

小蓝想用一个 6 面魔法骰子来测试自己的运气。抛掷这个骰子,点数1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,61,2,3,4,5,6朝上的概率分别为p 1 , p 2 , p 3 , p 4 , p 5 , p 6 p_1, p_2, p_3, p_4, p_5, p_6p1,p2,p3,p4,p5,p6

小蓝将连续抛掷这个骰子n nn次,并记录下每次抛掷的结果。令L LL为这n nn次结果中,数字6 66连续出现的最大长度。

现在,请你帮小蓝计算L LL的数学期望是多少。

注意:L LL的期望仅与数字6 66出现的概率p 6 p_6p6有关,其余概率p 1 , … , p 5 p_1,\dots,p_5p1,,p5仅用于保证骰子概率分布的完整性。

输入格式

输入共两行:

第一行包含一个正整数n nn,表示抛掷次数。

第二行包含6 66个用空格分隔的浮点数p 1 , p 2 , p 3 , p 4 , p 5 , p 6 p_1, p_2, p_3, p_4, p_5, p_6p1,p2,p3,p4,p5,p6,分别表示点数1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,61,2,3,4,5,6朝上的概率。

输出格式

输出一个浮点数,表示L LL的数学期望。结果四舍五入保留至小数点后两位。

输入输出样例 #1

输入 #1

10 0.1 0.2 0.2 0.1 0.2 0.2

输出 #1

1.23

说明/提示

【评测用例规模与约定】

对于30 % 30\%30%的评测用例,1 ≤ n ≤ 8 1 \leq n \leq 81n8

对于所有的评测用例,1 ≤ n ≤ 500 1 \leq n \leq 5001n500∑ i = 1 6 p i = 1 \sum_{i=1}^{6} p_i = 1i=16pi=1p i ∈ [ 0 , 1 ] p_i \in [0, 1]pi[0,1]。洛谷测试数据保证p i p_ipi小数点后不超过6 66位,且不会出现“卡精度”的极端构造案例。


Solution

1. 题意

投掷一枚可能不均匀的骰子n nn次,已知每个面出现的概率,求最长的连续出现6 66的次数L LL的数学期望。

2. 分析

对于非负整数随机变量L LL,其期望可以表示为:

E ( L ) = ∑ k = 1 n P ( L ≥ k ) E(L) = \sum_{k=1}^{n} P(L \ge k)E(L)=k=1nP(Lk)

即:期望等于所有P ( L ≥ k ) P(L \ge k)P(Lk)之和。而P ( L ≥ k ) P(L \ge k)P(Lk)表示“n nn次抛掷中至少出现一次连续k kk6 66”的概率。

由于直接求“至少一次”比较麻烦,我们转而求其对立事件:n nn次抛掷中一次都没有出现连续k kk6 66的概率,记为f ( i , k ) f(i,k)f(i,k)i ii次抛掷后)。
显然P ( L ≥ k ) = 1 − f ( n , k ) P(L \ge k) = 1 - f(n,k)P(Lk)=1f(n,k)

接下来就是老生常谈的 dp 了。

f ( i , k ) f(i,k)f(i,k)表示的是(i ii次试验没有连续k kk6 66的概率),p pp表示的是单次出6 66的概率。

i < k i < ki<k时,不可能出现连续k kk6 66,此时f ( i , k ) = 1 f(i,k) = 1f(i,k)=1

i = k i = ki=k时,只有全为6 66这一种情况不满足,故f ( i , k ) = 1 − p k f(i,k) = 1 - p^kf(i,k)=1pk

i > k i > ki>k时,可以从i − 1 i-1i1的状态转移过来。具体说来,若设g ( i , k ) g(i,k)g(i,k)表示的是第i ii次恰好首次形成连续k kk6 66,则:

f ( i , k ) = f ( i − 1 , k ) − g ( i , k ) f(i,k) = f(i-1,k) - g(i,k)f(i,k)=f(i1,k)g(i,k)

要使第i ii首次形成连续k kk6 66,序列末尾必须不为6 66,倒数第二次往前出现k kk6 66,且前i − k − 1 i-k-1ik1次没有出现过连续k kk6 66。其概率为g ( i , k ) = ( 1 − p ) ⋅ p k ⋅ f ( i − k − 1 , k ) g(i,k) = (1-p) \cdot p^k \cdot f(i-k-1,k)g(i,k)=(1p)pkf(ik1,k)

综上所述,转移方程就是

f ( i , k ) = { 1 , i < k 1 − p k , i = k f ( i − 1 , k ) − ( 1 − p ) ⋅ p k ⋅ f ( i − k − 1 , k ) , i > k f(i,k) = \begin{cases} 1 &, i < k \\ 1-p^k &, i=k \\ f(i-1,k) - (1-p) \cdot p^k \cdot f(i-k-1,k) &, i > k \end{cases}f(i,k)=11pkf(i1,k)(1p)pkf(ik1,k),i<k,i=k,i>k

汇总上面的结果,就得到了分布列(前面之所以有“1 − 1-1”是因为我们之前求的是对立事件的概率):

k kk0 001 112 22⋯ \cdotsk kk⋯ \cdotsn nn
至少出现一次k kk连的概率P ( L ≥ k ) P(L\ge k)P(Lk)1 − f ( n , 0 ) 1-f(n,0)1f(n,0)1 − f ( n , 1 ) 1-f(n,1)1f(n,1)1 − f ( n , 2 ) 1-f(n,2)1f(n,2)⋯ \cdots1 − f ( n , k ) 1-f(n,k)1f(n,k)⋯ \cdots1 − f ( n , n ) 1-f(n,n)1f(n,n)

由于这个概率是“至少出现一次k kk连”的概率,因此上述分布列的每一项概率都自动涵盖了具体出现k + 1 , k + 2 ⋯ k+1,k+2\cdotsk+1,k+2连的情况,只需要将上述分布列里的概率直接累加,就是最终的答案了。即

E ( L ) = ∑ k = 1 n [ 1 − f ( n , k ) ] = n − ∑ k = 1 n f ( n , k ) E(L) = \sum_{k=1}^n [1-f(n, k)] = \boxed{n - \sum_{k=1}^n f(n, k)}E(L)=k=1n[1f(n,k)]=nk=1nf(n,k)

特别的,将上面那个分布列里的相邻两项依次做差,能求得具体到“恰好出现k kk连”的概率。换句话说,上面的分布列类似于离散的累积概率分布,这种反着来的,自右往左累积的概率分布,一般称为互补累积分布函数(也叫右尾累积分布、生存函数等)。

最后总体的时间复杂度为O ( n 2 ) O(n^2)O(n2)

3. 代码

Python

importsysdefsolve()->None:data=sys.stdin.read().split()ifnotdata:returnn=int(data[0])p=float(data[6])q=1.0-pifp==0.0:print("0.00")returnifp==1.0:print(f"{n:.2f}")returnexpectation=0.0pk=pforkinrange(1,n+1):dp=[0.0]*(n+1)foriinrange(k):dp[i]=1.0dp[k]=1.0-pkforiinrange(k+1,n+1):dp[i]=dp[i-1]-q*pk*dp[i-k-1]prob_ge_k=1.0-dp[n]ifprob_ge_k<0.0:prob_ge_k=0.0ifprob_ge_k>1.0:prob_ge_k=1.0expectation+=prob_ge_k pk*=pprint(f"{expectation:.2f}")if__name__=="__main__":solve()

4. 轶事

  • 在电子游戏里,“连续出现”一般会使用英文单词 streak(n. 条纹、条带、一连串 v. 奔跑、留下条纹);题目里的L LL英语一般称为 longest streak。
  • 许多网站的连续登陆打卡也会使用这个单词(比如:Kaggle)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 23:30:37

Qt6 - QPlainText方法大全

1. setPlainText(QString text) 设置控件内的纯文本&#xff08;会清空原内容&#xff09;。 示例 plainTextEdit->setPlainText("这是纯文本内容"); 2. appendPlainText(QString text) 在末尾追加一行文本&#xff08;自动换行&#xff09;。 示例 plainTe…

作者头像 李华
网站建设 2026/5/26 23:26:04

猴子吃桃问题:逆向思维建模与多语言工业级实现

1. 这道题不是考编程&#xff0c;是考你有没有“逆向思维”的肌肉记忆“猴子吃桃”这道题&#xff0c;在国内各大厂、外企、校招笔试中反复出现&#xff0c;从2005年左右的C语言上机考试&#xff0c;到今天LeetCode周赛的Easy题变形&#xff0c;它始终没被淘汰——不是因为难&a…

作者头像 李华
网站建设 2026/5/26 23:17:21

从DRC到PEX:Calibre验证流程保姆级实操指南(附常见报错排查)

从DRC到PEX&#xff1a;Calibre验证流程保姆级实操指南&#xff08;附常见报错排查&#xff09;在集成电路设计领域&#xff0c;物理验证是确保芯片设计从图纸到硅片转换过程中准确无误的关键环节。作为业界标准的Calibre验证工具套件&#xff0c;其DRC&#xff08;设计规则检查…

作者头像 李华