hdu 4652(概率dp)

题目链接:点击打开链接;

题意:给定一个m个面的骰子然后给定两种询问,0 m n,表示求丢多少次使得最后丢的n次都相同的期望,1 m n表示求最后丢的n次两两不相同的期望。;

题目分析:

我们设dp[i]为当前为i个连续的数还需投掷次数的期望搭dp[0]就是解

在相同的情况:

dp[i] 记录的是已经连续i个相同,到n个不同需要的次数的数学期望
dp[0]= 1+dp[1]
dp[1]= 1+( 1/m*dp[2]+(m-1)/m*dp[1])=1+(dp[2]+(1-m)*dp[1])/m;
dp[2]= 1+(dp[3]+(1-m)*dp[1])/m;
....................
dp[n]= 0

可以推出dp[i] = 1 + ( (m-1)*dp[1] + dp[i+1] ) / m,dp[i+1] = 1 + ( (m-1)*dp[1] + dp[i+2] ) / m;

我们不难看出这是等比数列:dp[0]=(1-m^n)/(1-m);

然而求不同的时候:

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[i+1]= 1 + (dp[1] + dp[2] + ... dp[i] + dp[i+1] + (m-i-1)*dp[i+1]) / m
...
dp[n] = 0;

解得:dp[i] - dp[i+1] = (m-i-1)/m * (dp[i+1] - dp[i+2]);

因此:dp[0]-dp[1]=1;
dp[1]-dp[2]=1*m/(m-1);
dp[2]-dp[3]=1*m/(m-1)*m/(m-2);
..........

dp[n-1]-dp[n]=1*m/(m-1)*m/(m-2)*.......*m/(m-n+1);


累加起来就是答案
代码如下:

#include <set>
#include <queue>
#include <math.h>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <algorithm>
using namespace std;
int main(){
    int t;
    while(scanf("%d",&t)!=EOF){
        int x,n,m;
        while(t--){
            scanf("%d%d%d",&x,&n,&m);
            if(!(x&1)){
                double ans=0;
                for(int i=0;i<m;i++)
                ans+=pow(n+0.0,i);
                printf("%.9f\n",ans);//为0的时候就是等比数列前n项和
            }
            else{
                double ans=0;
                double tmp=1.0;
                for(int i=1;i<=m;i++){
                    ans+=tmp;
                    tmp=tmp*n/(n-i);
                }//为1的时候就如我上述所说
                printf("%.9f\n",ans);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(dp,概率DP)