zoukankan      html  css  js  c++  java
  • dice 概率论 概率DP

    题目链接:

    http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1010&cid=459

    找出公式,公式有实际意义,某种情形当重复做n次实验时会出现一次,即出现的概率为1/n,现在要想出现这种情形,平均要做多少次实验,显然平均要做n次。

    说一个具体的,比如掷色子,有6个点,6个点随机等概率出现。掷一次色子出现1的概率为1/6,现在想掷出1来,平均要掷色子多少次,即次数的数学期望是多少。

    可以证明:

    设掷i次色子才出现1的概率为p[i],则有

    p[1] = 1/6;

    p[2] = (5/6) *(1/6);第一次没有出现

    p[3] = (5/6)^2*(1/6)

    `````

    p[n] = (5/6)^n-1*(1/6);前n-1次没有出现

    ``````

    所以次数的数学期望为sum(k*p[k]),(k>=1,k为自然数,可以取到无穷)  ,据观察,有p[i] = p[i-1]*(5/6);

    式子1:s = 1*p[1] + 2*p[2] + ``` +n*p[n] +````

    式子2:(5/6)*s =     1*p[1] + ````(n-1)*p[n]+````(式子2为式子1的左右两边同时乘以5/6得到)

    用式子1-式子2得

    (1/6)*s = 1/6 + (1/6)*(5/6) + (1/6)*(5/6)^2````+(1/6)*(5/6)^n+```

    又等比数列的公式得(1/6)*s =( 1/6(1 -(5/6)^n)/(1-5/6).由于n为正无穷,所有(5/6)^n =0;所以s = 6.

    这个题的公式为:

    情形1,出现连续n个相同后停止掷色子的次数的期望 = 1+m+m^2 + ``` + m^(n-1);

    情形2,出现连续n个不同后停止掷色子的次数的期望 = 1+m/(m-1) + m^2/((m-1)*(m-2))+```+m^(n-1)/((m-1)*(m-2)*```*(m-n+1));

    可以这样解释,情形1,先随便掷色子一次,后面要掷出和这个相同的期望数为m,然后仍要掷出相同的期望为m^2```

    类推,后面要掷出和这个色子同色的概率为1/m,所以次数的期望为m。第三次掷色子要和前两次相同的概率为1/(m*m),所以期望为m*m```

    其余就自己推吧···(未必对···)

    另外一种方法:概率dp,摘自杭电解题报告

    设dp[i]表示当前在 已经投掷出 i个 不相同/相同 这个状态时期望还需要投掷多少次,然后dp[i] 有如下等式:

    相同:

        //dp[0] = 1 + dp[1]

        //dp[1] = 1 + ((m-1)dp[1] + dp[2]) / m

        //dp[i] = 1 + ((m-1)dp[1] + dp[i+1]) / m

        //...

        //dp[n] = 0;

    不相同:

        //dp[0] = 1 + dp[1]

        //dp[1] = 1 + (dp[1] + (m-1) dp[2]) / m

        //dp[2] = 1 + (dp[1] + dp[2] + (m-2) dp[3]) / m

        //dp[i] = 1 + (dp[1] + dp[2] + ... dp[i] + (m-i)dp[i+1]) / m

        //...

        //dp[n] = 0; 

    。。于是可以高斯消元。。对于第一问。。我们发现就是相当于 Typing Monkey 问题中字符串是 AAAA..AA 这一特殊情况。。解得递推式:

    dp[n] = 0

    dp[n-1] = dp[n] * m + 1

    。。。

    解开后等于等比数列求和。

    (也可以直接得到这个公式。。。因为在当前状态只有 m/1 的概率可以进入下一状态,否则要重新来过。。而这一步会另总的步数 + 1。)

    对于第二问。。

    现在设s[i]=sigma{dp[i], 1..i},对s[i] 列方程
    每个方程是关于三个相邻的s[i] 的,然后就可以线性时间解出来了。

    也可以设 d[i] = dp[i] - dp[i+1].

    可以得到 d[i] =  m * d[i-1]  / (m-i)

    然后就是解一元一次方程... 

    参见:

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13614

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21631

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24402

    http://www.cnblogs.com/ch3656468/archive/2011/05/04/2036332.html

    上面的两种递推式肯定能推出上面的公式来,所以我直接用公式写的

    贴代码:

     1 #include <cstdio>
     2 int main()
     3 {
     4 //    freopen("in.c","r",stdin);
     5     int t;
     6     while(scanf("%d",&t) != EOF)
     7     {
     8         while(t--)
     9         {
    10             double flag,m,n;
    11             scanf("%lf%lf%lf",&flag,&m,&n);
    12             double ans=1,tmp =1;
    13             if(flag == 0)
    14             {
    15                 for(int i=1; i<n; ++i)
    16                 {
    17                     tmp *= m;
    18                     ans += tmp;
    19 
    20                 }
    21             }
    22             else
    23             {
    24                 for(int i=1; i<n; ++i)
    25                 {
    26                     tmp *= (m/(m-i));
    27                     ans += tmp;
    28                 }
    29             }
    30             printf("%lf
    ",ans);
    31         }
    32     }
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/allh123/p/3246500.html
Copyright © 2011-2022 走看看