地址: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.
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
思路:前一个用套路就行了,但是后一个种类太多,用套路的话会超时。
看了下别人的做法,通过推导公式来求出答案,利用相减来去掉未知数从而找出关系。
这里只写后一种提问的推导过程:
因为要最后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;
}