「学习笔记」期望概率dp

一.数学期望的概念#

「学习笔记」期望问题 是学习期望概率dp的基础,建议学习后再来阅读该学习笔记。

数学期望(简称期望),是试验中每次可能结果的概率乘以其结果的总和,它反映了随机变量平均取值的大小。

数学期望可以用加权平均数来理解,可能取值就是初始数据,概率就是每个数的权,此时期望就是加权平均数。


二.数学期望的计算公式#

对于随机变量 X,它有 n 种可能的取值,取值为 xi 的概率为 P(xi),那么它的数学期望 E(X)=Σi=1nxiP(xi)

举个例子:给定一个随机变量 X,它有六种可能的取值,分别是 1,2,3,4,5,6,且取每个值得概率是一样的,那么 E(X)=16×1+16×2+16×3+16×4+16×5+16×6=72


三.数学期望的性质#

A,B,C 为常数, X,Y 为随机变量,那么有:

  • E(C)=C
  • E(CX)=CE(X)
  • 重点:E(X+Y)=E(X)+E(Y),线性性;
  • X,Y 互相独立时, E(XY)=E(X)E(Y)
  • 结合上列性质,得出 X,Y 互相独立时 E(AX+BY)=AE(X)+BE(Y)

四.期望dp#

求解达到某一目标的期望代价:因为最终的代价我们不知道,所以需要倒序求解。

fi,j 为在 (i,j) 这个状态实现目标的期望代价(相当于相距目标多少)。

当然我们也可以采用正序求解,只需要将状态的意义确定,符合要求,就可以求解。


五.例题讲解#

Ybtoj【例题1】路径长度#

P4316 绿豆蛙的归宿#

因为已知最终状态,按照期望dp的想法,我们采用逆推。

设有向边 xy,那么有 fx=(1degx)Σfy+wxy

因为反向建边,所以我们要把 x,y 颠倒过来。

DAG 上进行拓扑排序即可转移状态。

核心代码:

Copy
queue <int> q; q.push (n); while(!q.empty()) { int u = q.front(); q.pop(); for(int i=head[u]; i; i = e[i].from) { int v = e[i].to; f[v] += (f[u] + e[i].w) / dg[v]; if(--in[v] == 0) { q.push (v); } } }

Ybtoj【例题2】乘坐电梯#

CF518D Ilya and Escalator#

fi,j 为在第 i 个人,第 j 秒时电梯上的期望人数。

那么,易得 fi,j=(1p)×fi,j1+p×(fi1,j1+1)

最后输出 fn,t 即可。

Ybtoj【例题3】期望收益#

P1365 WJMZBMR打osu! / Easy#

先思考一下,在连续 ao 后面再加一个 o,会对答案产生多少贡献?

显然,会多贡献 (a+1)2a2=a2+1+2aa2=2a+1

当处理到第 i 位时,我们可以知道以第 i 位为结尾的连续 o 的期望长度,根据 连续 o 的期望长度,就可以轻松算出期望分数。

核心代码:

Copy
for (int i = 1; i <= n; i++) { if (c[i] == 'o') { ans += len * 2 + 1;//一定是,累计贡献。 len++;//同上。 } else if (c[i] == 'x') { len = 0;//一定不是,期望长度归0。 } else { ans += (len * 2 + 1) / 2;//有一半的概率不是o,所以要除以2。 len = (len + 1) / 2;//同上。 } }

Ybtoj【例题4】期望分数#

P1654 OSU!#

和上题相似,但是指数为 3

也思考一下,在连续 ao 后面再加一个 o,会对答案产生多少贡献?

计算出会多贡献 (a+1)3a3=a3+3a2+3a+1a3=3a2+3a+1

E(Xi) 为在第 i 位得的分数期望,我们思考一下 E(Xi)E(Xi+1) 的关系。

假设在 i 位置连续 1 串长度为 l 的概率为 pl,在 i+1 位置是 1 的概率为 P ,那么对于每一个单独的 l 它都有 P 的概率对分数产生 (3l2+3l+1)的额外贡献。

我们把所有可能的 l 一起考虑,就可以得到这个式子:
E(Xi+1)=E(Xi)+P×Σl=0ipl(3l2+3l+1)

然后我们将式子转化为:
E(Xi+1)=E(Xi)+P×(3E(li2)+3E(li)+1)

接下来维护 E(l)E(l2)

于是我们可以这么算:
E(li+1=P×(E(li)+1)

E(li+12=P×(E(li2)+2E(li)+1)

然后我们递推,用三个变量存储即可。

核心代码:

Copy
for (int i = 1; i <= n; i ++) { ans += (3 * len2 + 3 * len1 + 1) * p[i]; len2 = (len2 + 2 * len1 + 1) * p[i]; len1 = (len1 + 1) * p[i]; } printf ("%.1lf", ans);
posted @   cyhyyds  阅读(656)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示
CONTENTS