• SGU 495 Kids and Prizes:期望dp / 概率dp / 推公式


    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495

    题意:

      有n个礼物盒,m个人。

      最开始每个礼物盒中都有一个礼物。

      m个人依次随机选一个盒子,如果有礼物就拿走,然后放回空盒子。

      问你所有人得到总礼物数的期望。

    题解:

      三种做法:期望dp,概率dp,推公式

      一、期望dp

        表示状态:

          dp[i] = 该第i个人拿箱子时的总礼物的期望

        找出答案:

          ans = dp[m]

        如何转移:

          对于第i个人,拿到礼物或没拿到。

          (1)φ(没拿到) = dp[i]  P(没拿到) = dp[i]/n

          (2)φ(拿到) = dp[i]+1  P(拿到) = (n-dp[i])/n

          综上:dp[i+1] = dp[i] * dp[i]/n + (dp[i]+1) * (n-dp[i])/n

        边界条件:

          dp[0] = 0

          还没开始拿的时候礼物数为0

      二、概率dp

        表示状态:

          dp[i] = 第i个人拿到礼物的概率

        找出答案:

          ans = ∑ dp[i]

          每个人得到礼物的概率 * 得到礼物的数量(为1) 之和。

        如何转移:

          对于第i个人,拿到礼物或没拿到。

          (1)没拿到:dp[i+1]依然等于dp[i],没拿到礼物的概率为1-dp[i].

          (2)拿到:dp[i+1] = dp[i] - 1/n,拿到的概率为dp[i].

          综上:dp[i+1] = dp[i] * (1 - dp[i]) + (dp[i] - 1/n) * dp[i]

        边界条件:

          dp[0] = 1

          所有盒子里都有礼物,第0个人一定拿到礼物。

      三、推公式

        m个人是独立的。

        对于每个礼物不被人选中的概率为((n-1)/n)^m

        那么不被选中的礼物数的期望就是 n*((n-1)/n)^m

        所以答案就是 n-n*((n-1)/n)^m

    AC Code(expectation):

     1 // state expression:
     2 // dp[i] = expectation
     3 // i: considering ith person
     4 //
     5 // find the answer:
     6 // ans = dp[m]
     7 //
     8 // transferring:
     9 // dp[i+1] = dp[i] * dp[i]/n + (dp[i]+1) * (n-dp[i])/n
    10 //
    11 // boundary:
    12 // dp[0] = 0
    13 #include <iostream>
    14 #include <stdio.h>
    15 #include <string.h>
    16 #define MAX_M 100005
    17 
    18 using namespace std;
    19 
    20 int n,m;
    21 double dp[MAX_M];
    22 
    23 int main()
    24 {
    25     scanf("%d%d",&n,&m);
    26     for(int i=0;i<m;i++)
    27     {
    28         dp[i+1]=dp[i]*dp[i]/n+(dp[i]+1.0)*(n-dp[i])/n;
    29     }
    30     printf("%.10f
    ",dp[m]);
    31 }

    AC Code(probability):

     1 // state expression:
     2 // dp[i] = probability
     3 // i: ith person got a gift
     4 //
     5 // find the answer:
     6 // sigma dp[i]
     7 //
     8 // transferring:
     9 // dp[i+1] = dp[i] * (1 - dp[i]) + (dp[i] - 1/n) * dp[i]
    10 //
    11 // boundary:
    12 // dp[0] = 1
    13 #include <iostream>
    14 #include <stdio.h>
    15 #include <string.h>
    16 #define MAX_M 100005
    17 
    18 using namespace std;
    19 
    20 int n,m;
    21 double ans=0;
    22 double dp[MAX_M];
    23 
    24 int main()
    25 {
    26     scanf("%d%d",&n,&m);
    27     dp[0]=1;
    28     for(int i=0;i<m;i++)
    29     {
    30         dp[i+1]=dp[i]*(1.0-dp[i])+(dp[i]-1.0/n)*dp[i];
    31         ans+=dp[i];
    32     }
    33     printf("%.10f
    ",ans);
    34 }

    AC Code(公式):

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <math.h>
     5 
     6 using namespace std;
     7 
     8 int n,m;
     9 
    10 int main()
    11 {
    12     scanf("%d%d",&n,&m);
    13     printf("%.10f
    ",n-n*pow((n-1.0)/n,m));
    14 }
  • 相关阅读:
    不用加减乘除做加法
    求1+2+3+...+n
    孩子们的游戏(圆圈中最后剩下的数)
    扑克牌顺子
    翻转单词顺序列
    左旋转字符串
    和为S的两个数字
    和为S的连续正数序列
    毕设进度12
    毕设进度11
  • 原文地址:https://www.cnblogs.com/Leohh/p/7566376.html
Copyright © 2020-2023  润新知