标签:print namespace ems mem mes 多少 names case 就会
https://vjudge.net/problem/UVA-11427
每天晚上你都玩纸牌游戏,如果第一次就赢了就高高兴兴地去睡觉,否则就一直玩到(赢了的次数)/(玩了的次数)>p,才去睡觉。每一局的结果都是独立的,赢的概率是p,一天晚上最多玩n次,如果n次都没有达到睡觉的要求,那么就会灰心丧气地去睡觉,以后再也不玩了。问期望能玩多少个晚上。
1<=N<=3000
每天能不能提前睡觉是独立的,所以先计算每天提前睡觉的概率
但是按照玩的流程,提前睡觉的概率不好直接计算,因为先玩了才会发生提前睡觉这一瞬时事件
所以直接计算玩的概率
设$d(i,j)$为一直没有提前睡觉,玩了i次,赢了j次的概率,那么就很容易得到一个递推式,$d(i,j)=p\times d(i-1,j-1)+(1-p)\times d(i-1,j)$
$d(0,0)=1$,其余为0
那么灰心丧气地去睡觉的概率是$d(n,0)+d(n,1)+d(n,2)+\cdots+d(n,n)$,设为$Q$
期望为$E=1Q+2Q(1-Q)+3Q(1-Q)^2+\cdots$,是一个无穷求和
需要一点技巧
$\frac{E}{Q}=1+2(1-Q)+3(1-Q)^2+\cdots$
$\frac{E}{Q}\times(1-Q)=(1-Q)+2(1-Q)^2+3(1-Q)^3+\cdots$
$\frac{E}{Q}\times{Q}=E=1+(1-Q)+(1-Q)^2+(1-Q)^3+\cdots=\lim_{x\rightarrow +\infty}\frac{1-(1-Q)^x}{1-(1-Q)}=\frac{1}{Q}$
#include<cstdio> #include<cstring> using namespace std; #define REPE(i,a,b) for(int i=(a); i<=(b); i++) double d[107][107]; int main() { int N; scanf("%d", &N); int kase=0; while(0<N--) { int a,b,n; scanf("%d/%d%d", &a, &b, &n); double p=(double)a/b; memset(d,0,sizeof d); d[0][0]=1; REPE(i,1,n) { d[i][0]=d[i-1][0]*(1-p); REPE(j,1,n) { if(b*j<=a*i) d[i][j] = d[i-1][j-1]*p+d[i-1][j]*(1-p); } } double Q=0; REPE(i,0,n) Q+=d[n][i]; printf("Case #%d: %d\n", ++kase, int(1/Q)); } }
标签:print namespace ems mem mes 多少 names case 就会
原文地址:https://www.cnblogs.com/sahdsg/p/12787787.html