hdu4652(概率DP,推公式)

地址:http://acm.hdu.edu.cn/showproblem.php?pid=4652

Dice

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 344    Accepted Submission(s): 228
Special Judge


Problem Description
You have a dice with m faces, each face contains a distinct number. We assume when we tossing the dice, each face will occur randomly and uniformly. Now you have T query to answer, each query has one of the following form:
0 m n: ask for the expected number of tosses until the last n times results are all same.
1 m n: ask for the expected number of tosses until the last n consecutive results are pairwise different.
 

Input
The first line contains a number T.(1≤T≤100) The next T line each line contains a query as we mentioned above. (1≤m,n≤10 6) For second kind query, we guarantee n≤m. And in order to avoid potential precision issue, we guarantee the result for our query will not exceeding 10 9 in this problem.
 

Output
For each query, output the corresponding result. The answer will be considered correct if the absolute or relative error doesn't exceed 10 -6.
 

Sample Input
  
  
6 0 6 1 0 6 3 0 6 5 1 6 2 1 6 4 1 6 6 10 1 4534 25 1 1232 24 1 3213 15 1 4343 24 1 4343 9 1 65467 123 1 43434 100 1 34344 9 1 10001 15 1 1000000 2000
 

Sample Output
  
  
1.000000000 43.000000000 1555.000000000 2.200000000 7.600000000 83.200000000 25.586315824 26.015990037 15.176341160 24.541045769 9.027721917 127.908330426 103.975455253 9.003495515 15.056204472 4731.706620396
 

题意:有一个m面的骰子,问(0)最后n面数字相同要掷几次,求期望;(1)最后n面数字不同要掷几次,求期望。

思路:前一个用套路就行了,但是后一个种类太多,用套路的话会超时。

            看了下别人的做法,通过推导公式来求出答案,利用相减来去掉未知数从而找出关系。

            这里只写后一种提问的推导过程:

            因为要最后n次不同,也就是说你掷出的数字可能与你第i次掷出的数字相同,那么你现在就从完成了m次不同投掷变为完成m-i次不同投掷,所以这里有多种情况。

            写成一般套路的话就是:

            p[0]=p[1]+1;

            p[1]=(m-1)/m*p[2]+1/m*p[1];

            p[2]=(m-2)/m*p[3]+1/m*p[1]+1/m*p[2];

            p[3]=(m-3)/m*p[4]+1/m*p[1]+1/m*p[2]+1/m*p[3];

            。

            。

            。

            p[i]=(m-i)/m*p[i+1]+1/m*p[1]+……+1/m*p[i];

            发现p[i]-p[i+1]=(m-i-1)/m*(p[i+1]-p[i+2]),又因为p[0]=p[1]+1,所以这里可以写出公式递推得答案。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
//#include<algorithm>
using namespace std;
double p[2000010];
int main()
{
    int t,a,m,n;
    scanf("%d",&t);
    while(t--)
    {
        double ans;
        scanf("%d%d%d",&a,&m,&n);
        if(!a)  //求相同
        {
            p[n*2]=p[n*2+1]=0;
            for(int i=n-1;i>=1;i--)
            {
                p[i*2]=1.0/m*p[(i+1)*2]+1;
                p[i*2+1]=1.0/m*p[(i+1)*2+1]+(m-1)*1.0/m;
            }
            printf("%.9lf\n",p[2]/(1-p[3])+1);
        }
        else  //求不同
        {
            p[0]=1;
            for(int i=1;i<n;p[0]+=p[i],i++)
                p[i]=m*1.0/(m-i)*p[i-1];
            printf("%.9lf\n",p[0]);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值