http://acm.hdu.edu.cn/showproblem.php?pid=4870
Rating
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 433 Accepted Submission(s): 276
Special Judge
1.000000 0.814700
39.000000 82.181160
题解:首先我们想到的是推公式,以dp[i]代表从i*50-(i+1)*50的期望值。dp[0]和dp[1]需要单独处理。
dp[0]代表我们从0-50需要进行的场数,分成两种情况:1.成功,概率为p,期望为1*p
2.失败,概率1-p,期望为(1-p)*(1+dp[0])
-----所以dp[0]=1*p+(1-p)*(1+dp[0]) ,化简后dp[0]=1/p;
dp[1]代表我们从50-100的场数期望,分成两种情况:1.成功,概率为p,期望为1*p
2.失败,概率1-p,期望为(1-p)*(1+dp[0]+dp[1])
-----所以dp[1]=1*p+(1-p)*(1+dp[0]+dp[1]) ,化简后dp[1]=1+(1-p)/p*(1+dp[0]);
i>2,dp[i]的求法,分成两种情况:1.成功,概率为p,期望为1*p
2.失败,概率1-p,期望为(1-p)*(1+dp[i-2]+dp[i-1]+dp[i])
-----所以dp[1]=1*p+(1-p)*(1+dp[0]+dp[1]) ,化简后dp[1]=1+(1-p)/p*(1+dp[i-2]+dp[i-1]);
这样,因为要使用两个帐号进行比赛,所以我们最后到达的状态就是一个帐号rating=1000,另外一个=950,只需要进行dp求和就行了。
另外这题也能用高斯消元做,目前不会,正在学习
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<set>
#include<queue>
using namespace std;
#define nn 110000
typedef long long LL;
double p;
double dp[30];
int main()
{
while(cin>>p)
{
double sum=0;
dp[0]=1/p;
dp[1]=1/(p*p);
sum=dp[0]+dp[1];
int i;
for(i=2;i<=19;i++)
{
dp[i]=1+(1-p)/p*(1+dp[i-2]+dp[i-1]);
sum+=dp[i];
}
printf("%.6lf\n",sum+sum-dp[19]);
}
return 0;
}
,等待补充。