zoukankan      html  css  js  c++  java
  • 概率期望

    概率期望


    引:

    一个简单问题:

    在一条数轴上, 从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_{omegain 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
    ", t); continue; }
            g = gcd(sumx + sumy, n - cnty);
            printf("Case %d: %d/%d
    ", 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
    ", 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:

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

    [egin{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
    ", 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
    ", 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]|xge n ~and~yge 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
    ", dp[0][0]);
    

    难题

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

    好题

    题意概述:

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

    走一个门有个代价(x_i (1le 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)

    则期望

    [egin{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
    ", tnum, sumx / (double)x); continue; }
            if (x == 0) { printf("Case %d: -1
    ", 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
    ", 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
    ", 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
    ", g[n]);
        else printf("%.6f
    ", 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的状态, 选择概率/期望
    • 遇到高维的期望应当从高维开始推求出需要哪些低维的期望, 而不是把低维推向高维
    • 严谨写转移方程
  • 相关阅读:
    【Unity编程】欧拉角与万向节死锁(图文版)
    关于ListView中getView被重复调用的问题
    svn 错误集锦续
    android 无法生成R文件的原因剖析
    SVN下错误集锦
    视频文件格式
    国内各视频网站android pad客户端支持分辨率情况初步统计
    android 下的网络图片加载
    遇到问题描述:Android Please ensure that adb is correctly located at问题解决
    android 时间控件概述
  • 原文地址:https://www.cnblogs.com/Kuonji/p/11831840.html
Copyright © 2011-2022 走看看