ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数学期望 DP

2022-08-07 17:34:45  阅读:151  来源: 互联网

标签:骰子 期望 int cfrac 数学 DP dp mod


对于一组离散型随机变量,出现其中某一变量的概率乘以这一变量值,再求和,就是数学期望。

也就是:

\(E=∑\limits_{i=1}^n(p_i×v_i)\)
通过这个定义,我们可以感知到,所谓期望,其实表示的是一组离散型随机变量的平均水平。 也可认为是进行某件事能得到的平均结果,或者理想代价。所以它也可以叫做一组离散型随机变量的均值。这也是期望这个概念的实际意义。

关于期望的一些性质:

\(E(X+Y)=E(X)+E(Y)\)
\(E(XY)=E(X)E(Y)\)
\(E(aX+b)=aE(X)+b\)
\(E(c)=c\)
其中,当\(E(XY)=E(X)E(Y)\)的成立条件是X,Y相互独立。

以上是高中数学内容。在此重新提一下。

进行期望DP的时候,这些性质有时显得至关重要,可以帮助我们理解很多递推的转移。

ABC263E

题意:

有 \(n\) 个格子,在第 \(1 \sim n-1\) 个格子上,第 \(i\) 个格子上有一个骰子,面值为 \(0 \sim a_i\),投一次骰子,这些面值均匀出现。投到几,就往前走几格。

从 \(1\) 号格子出发,求到 \(n\) 号格子所要投的骰子个数的数学期望。

分析:

对于线性期望 DP,通常有两种 DP 方式:

  1. \(dp_i\) 表示从起始状态到 \(i\) 状态的数学期望。
  2. \(dp_i\) 表示从 \(i\) 状态到起始状态的数学期望。

转移的时候,第一种方式通常从前往后转,需要起始状态已知。第二种方式通常是从后往前转,需要终止状态已知。有的时候这两种方式可以互换,有的时候不可以,需要灵活使用。

本题先考虑使用第 \(2\) 种方式,因为我们知道一个点可以前往哪些点,比较方便。
设 \(dp_i\) 表示从 \(i\) 节点开始,到达 \(n\) 的数学期望。

先从有穷条件入手,即如果骰子可以投到 \(1 \sim a_i\)(这样不会出现在原地打转的情况,比较符合拓扑序,方便入手),那么应该怎么算。
显然,

\[dp_i = \cfrac{dp_{i+1}+dp_{i+2}+...+dp_{i+a_i}}{a_i} + 1 \]

(投到 \(1,2,...,a_i\) 每一种情况的概率是 \(\frac{1}{a_i}\);不论什么情况从 \(i\) 都要多投 \(1\) 粒骰子)

如果是原题的无穷条件呢?在这时,虽然有些情况需要投掷的骰子数量会趋于无穷,但这时的概率成指数型增长。数学期望依然收敛。怎么计算呢?
照算不误。(by ajh 大佬)

\[dp_i = \cfrac{dp_i+dp_{i+1}+dp_{i+2}+...+dp_{i+a_i}}{a_i+1}+1 \]

把 \(dp_i\) 提到左边有:

\[\cfrac{a_i}{a_i+1} dp_i=\cfrac{dp_{i+1}+dp_{i+2}+...+dp_{i+a_i}}{a_i+1} + 1 \]

那么,

\[dp_i=\cfrac{a_i+1}{a_i} (\cfrac{dp_{i+1}+dp_{i+2}+...+dp_{i+a_i}}{a_i+1} + 1) \\ =\cfrac{dp_{i+1}+dp_{i+2}+...+dp_{i+a_i}+a_i+1}{a_i} \]

时间复杂度 \(O(n \log \bmod)\),使用后缀和优化。

考虑证明。考虑 \(dp_i=\cfrac{\sum \limits_{j=1}^{a_i} dp_j} {a_i} + X + 1\),其中 \(X\) 为(待填坑)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1000000;
const int mod = 998244353;
int a[200010];
int dp[200010];
int suf[200010];
int qpow(int x, int k){
    int ans = 1;
    while(k) {
        if(k&1)ans=ans*x%mod;
        x=x*x%mod;
        k>>=1;
    }
    return ans;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //think twice,code once.
    //think once,debug forever.
    int n; cin >> n;
    f(i ,1,n)cin>>a[i];
    dp[n] = 0;
    for(int i = n-1;i >= 1; i--){
        int up = ((suf[i+1]-suf[i+a[i]+1])+a[i]+1+inf*mod) % mod;
        int down = a[i];
        dp[i] = up * qpow(down, mod - 2) % mod;
        suf[i] = (suf[i+1]+dp[i])%mod;
    }
    cout << dp[1] << endl;
    return 0;
}

标签:骰子,期望,int,cfrac,数学,DP,dp,mod
来源: https://www.cnblogs.com/Zeardoe/p/16559432.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有