[hdu4870]Rating

Rating

题解

分明8个月前才做过的,现在做又想了半天。

容易发现,两个账号打的轮数是可以分开考虑的,它们之间不会互相影响,而最后的情况肯定是一个账号的分数为19*50,另一个为20*50。

我们设g_{i}表示将一个账号的分数打到i*50的期望轮数,答案就是g_{19}+g_{20}

可以得到方程式,g_{i}= p(g_{i-1}+1)+(1-p)(g_{i+2}+1)

如果我们根据这个方程式来代换出g的值的话你会发现一个问题,就是g_{i}所对应的概率并不为1,因为它是逆推的,转化出来的递推式子是错误,它的答案也是错的。

我们考虑定义f_{i}为在分数为i*50时赢一轮的期望轮数,g_{i}可以用\sum_{j=0}^{i=1}f_{j}表示出来。

而关于f我们可以得到方程式f_{i}=p+(1+f_{i-1}+f_{i-2})(1-p)

稍微转化一下,f_{i}=\frac{(1+(1-p)(f_{i-1}+f_{i-2}))}{p}

这样就可以O\left(n \right )的处理出来所有f的值,再前缀和统计g即可。

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<time.h>
using namespace std;
#define MAXN 50
typedef long long LL;
#define gc() getchar()
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
}
double dp[MAXN],sum[MAXN],p;
int main(){
	while(scanf("%lf",&p)!=EOF){
		dp[0]=1/p;dp[1]=1/p+(1-p)/(p*p);sum[1]=dp[0]+dp[1];
		for(int i=2;i<=19;i++){
			dp[i]=(1+(1-p)*(dp[i-1]+dp[i-2]))/p;
			sum[i]=sum[i-1]+dp[i];
		}
		printf("%.6lf\n",sum[18]+sum[19]);
	}
	return 0;
}
/*
f{i}=p+(1-p)(1+f{i-2}+f{i-1}+f{i})
pf{i}=1+(1-p)(f{i-2}+f{i-1})
f{i}=(1+(1-p)(f{i-2}+f{i-1}))/p
dp{0}=1/p
dp{1}=(1+(1-p)f{0})/p
*/

谢谢!!!

posted @ 2020-09-08 21:14  StaroForgin  阅读(8)  评论(0)    收藏  举报  来源