Loading

概率与期望

概率

符号以及基本定义

1.Ω样本空间,也就是全集
2,F全集中的元素组合出的集合
3.\(P(A)\)表示A事件发生的概率,其中A是Ω的子集
eg:掷硬币,\(Ω={正面,反面,立起}\),那么F就是{{正面,反面,立起},{正面,反面},{正面,立起},{反面,立起},{正面},{正面},{反面},{立起},{}}其中抛不同次F也不一样.而P(正)=\({ \frac {1}{3}}\)
3.随机变量给随机现象结果标价的函数
eg:我们掷骰子,对于1,2,3,4,5,6,其实是我们对于掷到每个面结果标价而定义的
4.离散型随机变量(discrete random variable)是指所有可能取值能按确定次序逐一列出的随机变量,其值域为有限或可列无限多个数值---百度百科。
简单来说就是:1.结果有限 2.结果之间无序
eg:掷骰子,结果有限,掷出1,2也不一定连续
5.分布函数\(F(x_1)\),即是x从开始到x1的P(x)前缀和
eg:F(170)表示身高不超过170概率
性质:

  • 右连续性F(x)=F(x+0)
  • 在R上非严格单调递增
  • \(F(+\infty)=1,F(-\infty)=0\)
  • 随机变量与分布函数一一对应

古典概型

即数数,有两种方法
1.暴力数
2.用排列组合
然后算概率
**分类用加法,分步用乘法 **

条件概率

eg:在A发生的条件下,B发生的概率
公式:

\[P(A|B) = \frac{P(A \cap B)}{P(B)} \]

用图形理解: 2025-12-05 12-42-52屏幕截图
我们可以先考虑A发生的概率,然后将A作为样本空间算出粉色区域概率即可.(所以条件概率并不一定是\(P(A)*P(B)\))

全概率

就是一个概率既有分步,也有分类.
做法:画树状图
公式:

\[P(B) = \sum_{i=1}^k P(B|A_i)P(A_i) \]

计算一个事件发生的总概率
eg:小L做NOIP题,如果有思路会有90%概率AC,如果没思路会有25%的概率AC,有四题,其中2题有思路,2题没思路.求任意选择一题AC的概率

贝叶斯公式

本质:条件概率和全概率混合

\[P(A|B) = \frac{P(B|A)P(A)}{P(B)} \]

eg:还是上一个例子,只是问题改成: 已经A了一题,求A的是有思路的概率

事件的独立性

互斥

定义:有两个事件A,B&&\(A∩B=\)
eg:上120和没上60

对立

定义:有两个时间A,B&&\(A∩B=\)∅&&\(A \cup B=Ω\)
eg:及格和不及格

独立

独立无法用语言里解,需要用公式判定
公式\(P(A\cap B)=P(A)*P(B)\)

期望

符号以及基本定义

1.\(∫\)表示积分,即一定区间内对函数值的累加(类似物理加速度图像上如何求路程)
2.示性函数
对于随机变量的一个bool型函数,对于一定发生的事件为1,否则为0
eg:设一个事件为A,I为A的示性函数
那么如果\(w \in A 那么I(w)=1\)否则\(I(w)=0\)
3.若离散型随机变量的概率为\(P(A_i)\),那么期望公式为:\(E(X)=\sum P(X_i)*X_i\)
4.对于一个连续型随机变量X,其概率分布函数为f(X),dx表示将x分为连续的dx段\(E(X) = ∫_{-∞}^{∞} x f(x) dx\)其源头是这个式子\(E=\sum_{i=1}^{n} (F_i-F_{i-1})i\)

性质

1.\(E(aX+b)=a*E(x)+b(a,b \in R)\)
2.若随机变量X,Y存在,\(E(X+Y)=E(X)+E(Y)\)
3.\(EI_A\)=P(A)

条件期望

类似于条件概率
特殊性质:E(E(X|Y))=E(X)

例题

P1297 [国家集训队] 单选错位
首先发现问题可以简化成,有N个数排成的序列A,每个数循环右移一位变为B,求A,B中相同位置相同的数的个数.
发现N特别大,要么是dp要么是公式题
我们先考虑dp,发现一个位置要有贡献,那么必须前一个位置与这个位置的数一样,发现总的方案数是好求的.现在需要求\(\sum_{i=1}^{N} I_i\)其中\(I_i\)表示贡献为i的方案数.记sum[i]表示min(a[i],a[i-1]).那么答案就是\(\sum C_N^i\)但是发现还有许多细节,比如如果两个位置相差i,就不能算入\(I_i\).太复杂了并且没有模数,以至于存不下分母.所以我们考虑改换思路.
根据题目中小l的期望算法,和性质\(E(X+Y)=E(X)+E(Y)\).我们想到可以分开考虑每个位置期望然后加入答案,那么每个位置的期望可以分三种情况
1.a[i]==a[i-1],\(\displaystyle \frac {a_i}{a_i * a_{i-1}}\)
2.a[i]<a[i-1],\(\displaystyle \frac {a_i}{a_i * a_{i-1}}\)
3.a[i]>a[i-1],\(\displaystyle \frac {a_{i-1}}{a_i * a_{i-1}}\)
那么综上\(\sum \displaystyle \frac {1}{max(a_i,a_{i-1})}\)
小结:求期望时注意期望性质,尽量将题目用形式化语言概括
P1850 [NOIP 2016 提高组] 换教室期望dp好题
首先我们从特殊性质出发,考虑k=1的时候怎么做,那么就是一个简单的背包dp,再记一维表示这个时间段换不换,至于两两最短路,一个floyed就好。
那么如果k!=1要怎么办呢,发现如果不选仍然是一样的,如果选的话,有概率没选成.考虑再记一维表示是否选成,思考转移了,发现比较麻烦,因为首先是状态多,其次是dp[i][j][0/1][0/1]细节很多,容易算重,我们考虑能否减少状态.
显然之前的状态已经够用,我们只需要对于每次dis[i-1][i]乘上一些系数就可以.
那么分类:
1.如果i-1和i均不申请...
2.如果i-1和i均申请...
3.如果i-1申请,i不申请...
4.如果i申请,i-1不申请...
dirty work 具体请自行思考

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define N_ 2005
#define M_
#define P pair<ll,ll>
#define ld long double 
ll N,M,V,E,c[N_],d[N_],dis[N_][N_];
ld k[N_],dp[N_][N_][2],ans=1e9;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);std::cout.tie(0);
    cin>>N>>M>>V>>E;
    for(int i=1;i<=N;i++)cin>>c[i];
    for(int i=1;i<=N;i++)cin>>d[i];
    for(int i=1;i<=N;i++)cin>>k[i];
    memset(dis,0x3f,sizeof(dis));
    for(int i=0;i<=N;i++)
        for(int j=0;j<=M;j++)
        dp[i][j][0]=dp[i][j][1]=10000000000000;
    for(int i=1;i<=V;i++)dis[i][i]=0;
    for(int i=1;i<=E;i++)
    {
        ll u,v,w;cin>>u>>v>>w;
        dis[u][v]=dis[v][u]=min(dis[u][v],w);
    }
    if(N==1)cout<<"0.00",exit(0);
    for(int K=1;K<=V;K++)
        for(int i=1;i<=V;i++)
            for(int j=1;j<=V;j++)
            dis[i][j]=min(dis[i][K]+dis[K][j],dis[i][j]);
    //dp[i][j][1/0] stand for the ith position has j oppotunities to apply and this position apply or not 
    for(int i=1;i<N;i++)
        for(int j=M;j>=0;j--)
        {
            if(i==1){
                dp[1][M][0]=0;
                if(M>0)
                dp[1][M-1][1]=0;
            }
            dp[i+1][j][0]=min({dp[i+1][j][0],dp[i][j][0]+dis[c[i]][c[i+1]],dp[i][j][1]+dis[c[i]][c[i+1]]*(1-k[i])+dis[d[i]][c[i+1]]*k[i]});
            if(j<M)
            dp[i+1][j][1]=min({dp[i+1][j][1],dp[i][j+1][0]+dis[c[i]][c[i+1]]*(1-k[i+1])+dis[c[i]][d[i+1]]*k[i+1],dp[i][j+1][1]+dis[c[i]][c[i+1]]*(1-k[i])*(1-k[i+1])+dis[d[i]][c[i+1]]*k[i]*(1-k[i+1])+dis[c[i]][d[i+1]]*(1-k[i])*k[i+1]+dis[d[i]][d[i+1]]*k[i]*k[i+1]});
        }
    for(int i=0;i<=M;i++)
    ans=min({ans,dp[N][i][0],dp[N][i][1]});
    ans = round(ans*100)/100;
    std::cout<<fixed<<setprecision(2)<<ans<<'\n';
    return 0;
}

细节:注意N=1,有重边
小结:期望dp的是否成功一般不单独作为dp一个维度,而是融合在是否选这个维度之中
P2473 [SCOI2008] 奖励关一个关于枚举顺序的好题
首先,肯定有个思路就是令dp[i][s]表示在第i个位置时已经选的集合为S的最优期望
那么转移方程是简单的
dp[i+1][S|(1<<j)]=dp[i][S]+p[j](条件S&s[j]==s[j]),dp[i+1][S]=dp[i][S]
但是我们发现我们要的是最优期望,但是由于我们不知道未来的选择,所以这一步的最优期望不一定是之后的最优期望,也就是不满足最优子结构.
那么怎么办呢,我们的瓶颈是我们不知道未来的选择导致无法推导,可以想到如果我们换个方向从后往前推,那么就可记dp[i][S]表示到i时选了集合S,K的最优期望,那么转移是显然的,即如果能选就比较,不能选只好不选,每次的值/n取平均即可(因为不能选肯定是一种情况.可以选的话,选与不选因为是最优,所以只会出现一种情况.N个物品,那就是N的概率)

if((s[j]&S)==s[j])
	dp[i][S]+=max(dp[i+1][h],dp[i+1][S|(1<<j)]+p[j]);
else dp[i][S]+=dp[i+1][h];

这题是解决完了,但是什么时候用逆推,什么时候用顺推,是个好问题,这里总结了一下:
前提期望dp题
逆推
1.有选择权,因为我们无法用现在最优期望转移,所以要逆推
2.只有一个终止状态
顺推
1.求许多终止状态均求期望
2.随机期望
3.需要记录转移过程

练习


首先考虑设计状态,记dp[i],表示第i个人是最后一个的期望,但是发现根本无法转移,那么加一个状态表示还剩下j个人,即dp[i][j],表示还剩i个人,第j个人是最后一个被崩的期望.发现它是在环上,自然想到破环成链,但是我们发现,这个环不同于以往的环,因为一个人如果没有被崩掉是要被排回最后边的,那么就不能破环.
考虑先写出转移.(一下都是对于第一个人进行操作,相当于一个指针固定在1,然后,每个人循环往前移)
如果j==1时
那么不能崩他(因为我们要ta最后一个),而他前一个是i(因为是环),所以dp[i][1]=(1-p0)dp[i][i];
如果j>1时
有两种可能,一种是崩,那么人数会减少1,它的排名也会向前一个,如果不崩,那么第一个人排到最后,j的排名向前一个
dp[2][j]=P*dp[1][j-1]+dp[2][j-1]*(1-P);注意要滚动数组;
但是dp[i][1]怎么求呢,发现dp[i][1]=(1-p0)
dp[i][i];,那么解个方程就完了.
具体的:发现每个j都是上一个 * (1-p0)再加一个常数,那么将dp[i][i]转化为
d * dp[i][1]+sum带入就好

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
ll N,K;ld dp[3][10005],H[10005],P;
int main()
{
    cin>>P>>N>>K;
    H[0]=1;
    for(int i=1;i<=1e4;i++)H[i]=H[i-1]*(1-P);
    dp[1][1]=1;
    if(P==0&&K==1)cout<<"1.00000000",exit(0);
    if(P==0&&K!=1)cout<<"0.00000000",exit(0);
    for(int i=2;i<=N;i++)
    {
        ld sum=0;
        for(int j=2;j<=i;j++)sum=sum*(1-P)+dp[1][j-1]*P;
        dp[2][1]=sum*(1-P)*1.0/(1-H[i]);
        for(int j=2;j<=i;j++)
            dp[2][j]=P*dp[1][j-1]+dp[2][j-1]*(1-P);
        for(int j=1;j<=i;j++)dp[1][j]=dp[2][j];
    }
    cout<<fixed<<setprecision(8)<<dp[1][K];
    return 0;
}

小结:发现环上dp不是一定要破换成链,如果状态定义已经隐含了环的结构,就不需要,要大胆设计dp

posted @ 2025-12-06 10:29  leaf_ydc  阅读(2)  评论(0)    收藏  举报