概率期望

概率期望


引:

一个简单问题:

在一条数轴上, 从0点开始, 每一秒有一般的几率向正方向走一个单位, 有一半几率停着不动

问在\(0,1\)的概率与期望秒数


如果是停留在\(0\), 可以$f[0] = (f[0] + 1)*0.5 \(, 所以\)f[0]=1$

也可以\(\sum^{\infty}(\frac{1}{2})^i\)

但是发现算\(1\)的时候, 在\(n\)秒中, 可以随意选择其中一秒走一步, 其他停住, 这样答案算起会很大(\(\sum^{\infty}(\frac{1}{2})^i*i^2\))

显然错了, 因为到达自己之后仍然可以停留, 那么这个事件的定义就不明确了(既不是停留, 又不是到达)

如果是定义第一次到这个点的话, 就不能算自己到自己的这个事件, 这种傻逼问题之后可能又会碰到


基本定义

概率空间
\(\Omega\)
基本事件
(elementray event, 单元事件, 不可再分): \(\omega\)
事件
(event): \(A\)

\(\omega \in \Omega, \omega \in A, A \subseteq \Omega\)

\[P(\omega \in A)=\sum_{\omega\in A}P(\omega) \]

随机变量
(定义在\(\omega\)上): \(S\), 如\(S(\omega)\)定义为两个骰子点数和, 再例如"\(事件S(\omega)=7的概率\)"
独立的随机变量
如果同一个\(\Omega\)中的两个随机变量\(X,Y\), 有

\[P(X=x~and~Y=y)=P(X=x)* P(Y=y) \]

则称\(X,Y\)为独立的随机变量(这是定义)

套路

考虑每一步对期望的贡献

\(n\) 个点, 一开始全白, 每次某个概率选一个点染成黑色, 求期望全染黑的步数?

有期望的定义式可得: \(Ans = \sum_{i > 0} i \cdot Pr_{第 i 步恰好全黑}\)

考虑什么时候会走这个 $i步 , 即第 \(i\) 步时未全染黑的概率, 因为只要这时未全染黑, 后面无论何时染黑(后面情况加起来概率为1), 都需要走这一步, 所以这一步的贡献 = 概率

套路: 上述期望 = \(\sum_{i > 0} Pr_{第 i 步没有全黑的概率}\)


简单题

LightOJ1027 A Dangerous Maze <简单>

假迷宫, 假如门的代价是正数, 就可以花这个代价出去, 否则要花绝对值的代价, 留在原地

问出去的期望

\(E = \sum \frac{1}{n}*cost_i+\sum \frac{1}{n}*(cost_i + E)\)

化简即可

int T = in();
    for (int t = 1; t <= T; ++ t)
    {
        n = in();
        int sumx = 0, sumy = 0, cnty = 0, g = 0;
        for (int i = 1; i <= n; ++ i)
        {
            int x = in();
            if (x > 0) sumx += x; else sumy -= x, ++ cnty;
        }
        if (sumx == 0) { printf("Case %d: inf\n", t); continue; }
        g = gcd(sumx + sumy, n - cnty);
        printf("Case %d: %d/%d\n", t, (sumx + sumy) / g, (n - cnty) / g);
    }

LightOJ1030 Discovering Gold <简单>

金矿有\(n\)个, 每个金矿有一定收益, 一开始在\(1\), 投骰子\([1,6]\), 假如走这些步数后\(>n\)就一直投直到\(\le n\), 求到\(n\)时期望收益

	memset(f, 0, sizeof f);
    for (int i = n - 1; i >= 1; -- i)
    {
        int p = min(6, n - i);
        for (int j = 1; j <= p; ++ j)
           f[i] += (f[i + j] + val[i + j]) / (double)p;
    }
    ans = f[1] + val[1];

LightOJ1038 Race to 1 Again <预处理?!>

\(T(\le 10)\)组数据, 每次给出\(N(\le 10^5)\)

每个数有相同几率跳到他的因数(包括自己), 求跳到\(1\)的期望步数

\(cnt\)\(i\)的因数个数, \(f[i]=\frac{1}{cnt}*\sum f[j]+1\)

\((1-\frac{1}{cnt})f[i]=\frac{1}{cnt} \sum ^{!=i}f[j]+1\)

\(f[i]=(\sum^{!=i}f[j]+cnt) / (cnt - 1)\)

所有\(10^5\)以内都可以一遍\(DP\)预处理

int T, n;

double dp[MAXN];

void init()
{
    for (int i = 2; i <= 100000; ++ i)
    {
        double sum = 0, cnt = 0;
        for (int j = 1; j * j <= i; ++ j)
        {
            if (i % j != 0) continue;
            sum += dp[j], cnt += 1;
            if (i / j != j) sum += dp[i / j], cnt += 1;
        }
        dp[i] = (sum + cnt) / (cnt - 1);
    }
}

int main()
{
    init();
    T = in();
    for (int i = 1; i <= T; ++ i)
    {
        n = in();
        printf("Case %d: %.6lf\n", i, dp[n]);
    }
    return 0;
}

LightOJ1248 Dice (III) <期望初步>

\(n\)面的均匀的骰子每一面都投到的期望次数

\(E_i\)表示已经有\(i\)个不同的面时的期望

那么\(E_i = 1 + \frac{i}{n}E[i]+\frac{n-i}{n}E[i+1]\)

意思是说: 现在投一次, 有\(i/n\)的几率投到出现过的, 那么又回到\(i\)这个点, 还有剩下几率投到新的面

LightOJ1104 Birthday Paradox <正难则反>

求当一年为\(n(\le 10^5)\)天时, 至少要多少人, 才能满足他们中至少有两人生日相同的概率\(\ge 0.5\)

Sol:

竟然不会....

至少有两人相同可以转化成\(1.0-\)所有人都不相同的概率

BZOJ2752: HAOI2012高速公路 <假期望>

\(n(\le 10^5)\)个点, 相邻两点之间有边权, 初始是\(0\)

\(M(\le 10^5)\)个询问/操作, 操作是将\([l, r]\)之间的边权都加上一个值, 查询是问在\([l,r]\)中选两个不同的点, 他们之间边权和的期望

Sol:

假期望, 这是所有选择的边权和的和, 让它取除以方案数\(\tbinom{r-l+1}{2}\)

\[\begin{align} &=\sum_{i=l}^{r}sum[i]*(i-l)-\sum_{i=l}^{r}sum[i]*(r-i)\\ &=\sum_{i=l}^{r}sum[i]*(i-l-r+i)\\ &=\sum_{i=l}^{r}sum[i]*(2*i-r-l)\\ \end{align} \]

中等

LightOJ1151 Snakes and Ladders <高斯消元>

自以为思路很正确, 实则漏洞百出

\(1*100\)的棋盘上, 每个点至多有一个单向传送, 起点和终点不会有传送

可以扔一个\(6\)面的骰子, 假设投到\(x\), 然后花一步跳到往后数\(x\)个格子上, 如果超过\(100\)就重新投(但是要花费步数)

问期望几次从\(1\)到达\(100\)

Sol:

因为传送是xjb乱传的, 不能递推, 用高斯消元

考虑期望方程(读清题意!!!)

能传送和不能传送的点是不同的, 能传送的点根本就不能有任何操作直接传送到那个点!!!

能传送:

\[E_{now}=E{nex} \]

不能传送:

\[E_{now}=1+\frac{1}{6}*(\sum_{nex<=100}E_{nex} + min(0, i+6-100)*E_{now}) \]

可以根据这些列出方程

int n, to[MAXN];
DB a[MAXN][MAXN];
DB ansx[MAXN];

void check(int n)
{
    puts("------");
    for (int i = 1; i <= n; ++ i)
    {
        for (int j = 1; j <= n + 1; ++ j)
            printf("%.1f ", a[i][j]);
        puts("");
    }
    puts("------");
}
bool nosol, mulsol;
void Gauss(int n) 
{
    int r = 1, c = 1, maxr = 0;
    for (; r <= n && c <= n; ++ r, ++ c)
    {
        maxr = r;
        for (int i = r + 1; i <= n; ++ i) 
            if (fabs(a[i][c]) - fabs(a[maxr][c]) > EPS) maxr = i;
        if (maxr != r) 
            for (int i = 1; i <= n + 1; ++ i) // n + 1 !!!
                swap(a[r][i], a[maxr][i]);
        if (fabs(a[r][c]) < EPS) { -- r; continue; }
        for (int i = r + 1; i <= n; ++ i)
        {
            double k = a[i][c] / a[r][c];
            for (int j = c; j <= n + 1; ++ j) 
                a[i][j] = a[i][j] - k * a[r][j];
        }
    }
    -- r, -- c;
    for (int i = n; i >= 1; -- i)
    {
        int all0 = 1;
        for (int j = i; j <= n; ++ j) all0 &= (fabs(a[i][j]) < EPS);
        if (all0)
        {
            if (fabs(a[i][n + 1]) > EPS) nosol = true;
            else mulsol = true;
        }
        else 
        {
            for (int j = i + 1; j <= n; ++ j)
                a[i][n + 1] -= ansx[j] * a[i][j];
            ansx[i] = a[i][n + 1] / a[i][i];
        }
    }
} 

int main()
{
    int T = in();
    for (int t = 1; t <= T; ++ t)
    {
        memset(ansx, 0, sizeof ansx);
        memset(a, 0, sizeof a);
        memset(to, 0, sizeof to);
        n = in();
        for (int i = 1; i <= n; ++ i)
        {
            int x = in(), y = in();
            to[x] = y;
            a[x][x] = 1; a[x][y] = -1;
        }
        for (int i = 1; i <= 100 - 1; ++ i)
        {
            if (to[i]) continue;
            a[i][i] = min(6, 100 - i);
            for (int x = 1; x <= min(6, 100 - i); ++ x)
                a[i][i + x] = -1;
            a[i][101] = 6;
        }
        a[100][100] = 1;
        Gauss(100);
        printf("Case %d: %.7f\n", t, ansx[1]);
    }
    return 0;
}

LightOJ 1079 Just another Robbery <正难则反>

\(100\) 组数据, 每组\(\le 100\)个银行, 每个银行有一个被抓住的几率, 和成功时获得的收益(\(\le 100\))

问当总的被抓的几率\(\le lim\)时能获得的最大收益

其实算没被抓的几率就可以了

也可以像我一样傻逼的算被抓的几率:

  • 证明以不同顺序抢同一些银行被抓的几率相同
    • 列一下式子, 发现是容斥, 证毕
  • 证明抢一组银行的被抓/没被抓的几率可以整合, 视作一个合体银行
    • 被抓=\(a+(1-a)*b+(1-a)*(1-b)*c=P_{ab}+(1-P_{ab})*c\)
    • 展开发现一样, 也是容斥, 或者感性理解也行

好了, 滚动(一开始忘记)背包, 下标是收益

for (int k = 1; k <= T; ++ k)
    {
        sum = ans = tot = 0;
        scanf("%lf%d", &lim, &n);
        for (int i = 0; i <= 10000; ++ i) f[i] = 1; f[0] = 0;
        for (int i = 1; i <= n; ++ i)
        {
            int x; double y;
            scanf("%d%lf", &x, &y);
            if (y <= lim) 
            {
                ++ tot;
                c[tot] = y, v[tot] = x;
                sum += x;
            }
        }
        for (int i = 1; i <= tot; ++ i)
            for (int j = sum; j >= v[i]; -- j)
                f[j] = min(f[j], f[j - v[i]] + (1 - f[j - v[i]]) * c[i]);
        for (int i = sum; i >= 0; -- i)
            if (f[i] <= lim) { ans = i; break; }
        printf("Case %d: %d\n", k, ans);
    }

XJOI20190725T3游戏 <假博弈真期望>

Alice和Bob两个人正在玩一个游戏,游戏有很多种任务,难度为p的任务(p是正整数),有1/(2p)的概率完成并得到2(p-1)分,如果完成不了,得0分。一开始每人都是0分,从Alice开始轮流做任务,她可以选择任意一个任务来做;而Bob只会做难度为1的任务。只要其中有一个人达到n分,即算作那个人胜利。求Alice采取最优策略的情况下获胜的概率。

输入格式:

一个正整数n,含义如题目所述。

输出格式:

一个数,表示Alice获胜的概率,保留6位小数。

样例输入:

1

样例输出:

0.666667

数据范围:

对于30%的数据,n≤10

对于100%的数据,n≤500

乍一看以为是博弈论

没想到是枚举所有状态进行概率\(DP\)

\(DP[i][j]\)表示\(A, B\)分别为\(i,j\)时到达赢的状态的概率, 倒着推

那就枚举所有的任务来转移, 取其中最大的转移

\(DP[x][y]|x\ge n ~and~y\ge n\)全部设成\(1.0\), 这样就不用考虑边界要不要乘\(B\)的概率的问题(想想为什么?)

for (int i = 1; i <= 10; ++ i) 
        val[i] = 1 << (i - 1), p[i] = 1 << i;
    n = in();
    for (int j = n; j <= 1024; ++ j)
        for (int i = 0; i <= n; ++ i) 
            dp[j][i] = 1.0;
    for (int i = n - 1; i >= 0; -- i)
    {
        for (int j = n - 1; j >= 0; -- j)
        {
            double tmp = 0.0;
            for (int x = 1; x <= 10; ++ x)
            {
                tmp = max(tmp, ((dp[i + val[x]][j + 1] + dp[i + val[x]][j]) * 1.0 / (double)p[x] * 0.5 
                                + dp[i][j + 1] * (1.0 - 1.0 / (double)p[x]) * 0.5)
                          / (1.0 - (1.0 - 1.0 / (double)p[x]) * 0.5));
            }
            dp[i][j] = tmp;
        }
    }
    printf("%.6f\n", dp[0][0]);

难题

LightOJ - 1395 A Dangerous Maze (II) <!!!SO HARD!!!>

好题

题意概述:

你在一个迷宫里(假), 起点有\(n(\le 100)\)个门

走一个门有个代价\(x_i (1\le abs(x_i)\le10000)\), 如果是正数, 就可以花费这个代价离开迷宫, 如果是负数, 花费代价的绝对值, 仍然停留在原地

但是你只能记住最后访问的\(k(\le 100)\)个门, 你不会走这些门(因为你还待在迷宫里, 意味着那些门不能出去), 而其他门是随机选择的

问期望离开迷宫的代价

Sample Input

4

2 0
10 10
 
2 0
10 -10

3 1
10 -10 -20 

3 2
10 -10 -20

Sample Output

Case 1: 10
Case 2: 20.000
Case 3: 30.0000000000
Case 4: 25.0000000000

Sol:

先考虑没有记忆的情况, 即每次都随机选门, 设能出去的门个数为\(x\), 不能出去的为\(y\)

则期望

\[\begin{align} E &= \sum (\frac{x_i}{n})+\sum(\frac{y_i+E}{n}) \\ &= \frac{1}{n}*\sum x_i+\frac{1}{n}*\sum y_i + \frac{cnt_y}{n}*E \\ (1 - \frac{cnt_y}{n})*E &= \frac{1}{n}*(\sum x_i+\sum y_i) \end{align} \]

那么有记忆呢?

  • 首先\(k = \min(n,k)\)

假设当前记住的状态为\(now\), 记住了\(i\)

这是候选项是\(n - i\), 不能出去的门还剩\(y-i\)

\[E[i][now] = \frac{1}{n-i}\sum x + \frac{1}{n-i}\sum (y_{remain} + E[i+1][nex]) \]

\(k=i\)时略有不同

\[E[k][now] = \frac{1}{n-i}\sum x + \frac{1}{n-i}\sum (y_{remain} + E[k][nex]) \]

可以发现因为这些式子加好后面枚举了剩下的门, 所以这些期望方程大概形成了树型的关系

但是每个状态不同, 剩下的门也不同, 怎么办

可以把树上同一层的式子\(E[i]\)加起来, 把\(E[i]\)作为一个整体来算

感性发现因该是

\[E[i]= \frac{1}{n-i}\sum x + \frac{y-i}{n-i}(\frac{\sum y}{cnty} + E[i+1]) \]

倒着推就行了, 理性证明见这里

int T, n, m;
int x, y;
double sumx, sumy;
double p[106];

int main()
{
    scanf("%d", &T);
    for (int tnum = 1; tnum <= T; ++ tnum)
    {
        x = y = 0; sumx = sumy = 0.0;
        n = in(), m = in();
        p[0] = 0.0;
        for (int i = 1; i <= n; ++ i)
        {
            p[i] = 0.0;
            int tmp = in();
            if (tmp >= 0) ++ x, sumx += tmp;
            else ++ y, sumy -= tmp;
        }
        if (y == 0) { printf("Case %d: %.9f\n", tnum, sumx / (double)x); continue; }
        if (x == 0) { printf("Case %d: -1\n", tnum); continue; }
        m = min(m, y); 
        p[m] = (double)(sumx + (y - m) * sumy / (double)y) / (double)(n - m) / (1.0 - (double)(y - m) / (double)(n - m)) ;
        for (int i = m - 1; i >= 0; -- i)
        	p[i] = (sumx + (double)(y - i) * (sumy / (double)y + p[i + 1])) / (double)(n - i);
        printf("Case %d: %.9f\n", tnum, p[0]);
    }
    return 0;
}

BZOJ1076: [SCOI2008]奖励关 <较难>

发放\(k(\le 100)\)轮宝物, 每次随机发放\(n(\le 15)\)个宝物其中一个, 即每次对于所有宝物几率都为\(\frac{1}{n}\)

宝物的价值可能为负(\(\in [-10^6, 10^6]\)), 并且拿取宝物有先决条件, 要满足当前已经有某些宝物

你可以决策收不收取这轮的宝物(不满足先决条件时一定不能收取), 求在所有可能的情况下最优决策得到的平均价值

Sol:

最有决策的平均价值是什么意思?

即对于当前这个状态, 有\(n\)种转移, 每种转移又有取与不取两种决策, 最优决策当然是取收益大的那个决策, 而平均价值则是把每个转移两个里较大的那个加起来, 再除以\(n\)

要怎么知道转移后收不收取那个更优呢? 想到了倒着推

\(f[i][sta]\)表示到第\(i\)轮时, 每个宝物是否拥有的情况为\(sta\), 到末状态的最优决策的平均价值

//BZOJ MLE返回TLE	
scanf("%d%d", &m, &n);
    for (int i = 1; i <= n; ++ i)
    {
        scanf("%d", &val[i]);
        while (true)
        {
            int x; scanf("%d", &x);
            if (!x) break;
            prem[i] |= (1 << (x - 1));
        }
    }
    for (int i = m - 1; i >= 0; -- i)
    {
        for (int now = 0; now < (1 << n); ++ now)
        {
            for (int j = 1; j <= n; ++ j)
            {
                if ((now | prem[j]) != now) f[i][now] += f[i + 1][now];
                else f[i][now] += max(f[i + 1][now | (1 << (j - 1))] + val[j], f[i + 1][now]);
            }
            f[i][now] /= (double)n;
        }
    }
    printf("%.6f\n", f[0][0]);

BZOJ1426 收集邮票 <辅助期望>

神题:

有n种不同的邮票,每次只能买一张,并且买到的邮票究竟是n种邮票中的哪一种是等概率的,概率均为1/n,购买第k张邮票需要支付k元钱。
求得到所有种类的邮票需要花费的钱数目的期望。

input
3
output
21.25

Sol:

\(f[i]\)为有了\(i\)张时, 期望再买几次能凑齐, \(g[i]\)为...时期望代价

\(f[i]=\frac{i}{n}f[i]+\frac{n-i}{n}f[i+1]+1\)
\(g[i]=\frac{i}{n}(g[i]+f[i]+1)+\frac{n-i}{n}(g[i+1]+f[i+1]+1)\)

即把当前花费当做\(1\), 其他一次增长, 因为反正都是花费这些数, 知道总共花费几次, 花费的顺序是无所谓的

BZOJ2830: SHOI2012 随机树 <树上子问题>

初始树上只有一个点, 定义根节点深度为\(0\)
每次操作随机选择一个叶子, 给他增加两个儿子

求有\(n\)个叶子时, 叶子深度的平均值的期望, 和树深度的期望

Sol:

乍一看以为第一问比较难, 其实他比较简单

第二问:
显然是DP, 这种题在于如何选择DP的状态, 以及选择算期望/算概率, 还有借用辅助的概率/期望, 如果定义好了DP, 那么推一下是不难的

一开始想了几种一维的DP(每次要么选择最深点, 深度++, 否则深度不变), 还想过借用算大小为\(i\)的树深度为\(j\)的叶子个数的期望值来推, 都不行

观察一下这道题, 期望的深度是实数, 而对于每一种可能他的深度是整数, 而概率是实数, 不妨计算每一个深度出现的概率

如果想到左右子树分别是一个子问题的话, 这道题目就好做了, 而不是把所有叶子节点根据深度分类, 这样并不能简化问题

\(f[i][j]\)表示叶子有\(i\)个时, 深度是\(j\)的概率, 那么枚举左右字数叶子个数以及深度, 再加一个前缀和优化即可

double g[MAXN];
double f[MAXN][MAXN], p[MAXN][MAXN], t[MAXN][MAXN];
double solve(int n)
{
    p[1][1] = 1;
    for (int i = 3; i <= n; ++ i)
    {
	for (int j = 1; j < i; ++ j)
	{
	    if (j > 1) p[j][i - j] += p[j - 1][i - j] * (DB)(j - 1);
	    if (i - j > 1) p[j][i - j] += p[j][i - j - 1] * (DB)(i - j - 1);
	    p[j][i - j] /= (double)(i - 1);
	}
    }
    f[1][0] = t[1][0] = 1.0; f[2][1] = 1.0;
    for (int i = 1; i <= n; ++ i) t[1][i] = t[2][i] = 1.0;
    for (int i = 3; i <= n; ++ i)
    {
	for (int j = 1; j < i; ++ j)
	{
	    for (int ls = 1; ls < i; ++ ls)
	    {
		if (j > 1) 
		    f[i][j] += (f[ls][j - 1] * t[i - ls][j - 2] + f[i - ls][j - 1] * t[ls][j - 2]) * p[ls][i - ls];
		f[i][j] += f[ls][j - 1] * f[i - ls][j - 1] * p[ls][i - ls];
	    }
	    t[i][j] = t[i][j - 1] + f[i][j];
	}
	for (int j = i; j <= n; ++ j) t[i][j] = t[i][j - 1] + f[i][j];
    }
    double ret = 0;
    for (int i = 1; i < n; ++ i) ret += 1.0 * i * f[n][i];
    return ret;
}

int main()
{
    m = in(); n = in();
    for (int i = 2; i <= n; ++ i) g[i] = g[i - 1] + 2 / (1.0 * i);
    if (m == 1) printf("%.6f\n", g[n]);
    else printf("%.6f\n", solve(n));
    return 0;
}

Codeforces 235B Let's Play Osu!

有长度为\(n\)\(01\)串, 第\(i\)个位置有\(pi\)的几率是\(1\), 否则为\(0\)
一个串的值为每一段最长连续的\(1\)的长度的平方的和

求期望值

20191002 Cyanic Contest Problem C. Fibonacci’s Nightmare <推式子>

定义一个随机线性递推序列(即random linear recursive sequence, RLRS)是一个由如下方式生成的非负整数序列。一开始,令\(a_0= 1\)。然后对于从\(1\)开始的每一个\(n\),独立且等概率在\([0, n−1]\)中随机\(k\)个非负整数\(i_1, i_2,···, i_k,\)\(a_n=∑^k_{j=1}a_{i_j}\)。接下来是一个例子。令\(k= 2\),那么有\(a_1=a_0+a_0= 2\),之后,\(a_2\)的值等概率从\(a_0+a_0, a_0+a_1, a_1+a_0, a_1+a_1\)中选择。小C解决了\(k= 2\)\(a^2_n\)的数学期望。她想问你对于更大的\(k\)\(E(a^k_n)\)在模\(998244353\)下的值

这里的\(E(a^k_n)\)\((a_n)^k\)的期望

Sol:
对于\(k=2\)
\(f(n) = E((a_n)^2)\)

\[f(n) = E((a_i+a_j)^2)=E(a_i^2+a_j^2+2a_ia_j) \]

发现还需要一个\(g(n)=E(\sum_{i=0}^{n}a_i^2),t(n)=E(\sum_{i=0}^{n}\sum_{j=0}^{n}a_ia_j)\)

\[f(n) = \frac{2g(n-1)}{n}+\frac{2t(n-1)}{n*n} \]

\[g(n)=\sum{g(n-1)+a_n}*p=g(n-1)+f(n) \]

\(t(n)\)就比较麻烦了

\[t(n)=E(\sum_{i=0}^{n}\sum_{j=0}^{n}a_ia_j)\\ =E(\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}a_ia_j)+2*E(\sum_{i=0}^{n-1}a_i*a_n)+f(n)\\ =E(\sum_{i=0}^{n-1}\sum_{j=0}^{n-1}a_ia_j)+2*\sum_{i=1}^{...}(P_i*\sum_{i=0}^{n-1}a_i*\frac{2*\sum_{i=0}^{n-1}a_i}{n})+f(n)(P_i指一种排列的概率)\\ =t(n-1)+f(n)+\frac{4}{n}E((\sum_{i=0}^{n-1}a_i)^2)\\ =t(n-1)+\frac{4}{n}t(n-1)+f(n)\\ \]

NOIP2016换教室<期望DP + 神奇状态?多个状态加一起>

\(n\)个课程, 可以申请\(m\)次换教室, 第\(i\)个课程如果申请后成功则去\(d_i\), 失败或不申请都是在\(c_i\), 概率给定
一次性申请, 确定教室后依次走最短路到下一个教室(给图)
问怎样申请期望走的路最短, 输出这个值

Sol:
\(f[i][j][0/1]\)表示到第\(i\)个教室时申请了\(j\)次, 这次是否申请, 的最小期望

注意不是是否换教室, 而是是否申请, 因为题目要求一次性申请, 前者可能会有一步一步决策的问题; 而后者是一次选择选不选, 所以是正确的

其实选了的DP值是包含两个状态的, 转移时一起考虑其实跟分开考虑是一样的(画分支想想为什么)

总结

  • 子问题
  • 前缀和优化
  • 递推式-->通向式
  • 式子化简
  • 设置DP的状态, 选择概率/期望
  • 遇到高维的期望应当从高维开始推求出需要哪些低维的期望, 而不是把低维推向高维
  • 严谨写转移方程
posted @ 2019-11-10 21:07  Kuonji  阅读(592)  评论(0编辑  收藏  举报
nmdp