UVA 11427 Expect the Expected

https://vjudge.net/problem/UVA-11427

题目

每天晚上你都玩纸牌游戏,如果第一次就赢了就高高兴兴地去睡觉,否则就一直玩到(赢了的次数)/(玩了的次数)>p,才去睡觉。每一局的结果都是独立的,赢的概率是p,一天晚上最多玩n次,如果n次都没有达到睡觉的要求,那么就会灰心丧气地去睡觉,以后再也不玩了。问期望能玩多少个晚上。

1<=N<=3000

题解

每天能不能提前睡觉是独立的,所以先计算每天提前睡觉的概率

但是按照玩的流程,提前睡觉的概率不好直接计算,因为先玩了才会发生提前睡觉这一瞬时事件

所以直接计算玩的概率

设$d(i,j)$为一直没有提前睡觉,玩了i次,赢了j次的概率,那么就很容易得到一个递推式,$d(i,j)=p imes d(i-1,j-1)+(1-p) imes 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} imes(1-Q)=(1-Q)+2(1-Q)^2+3(1-Q)^3+cdots$

$frac{E}{Q} imes{Q}=E=1+(1-Q)+(1-Q)^2+(1-Q)^3+cdots=lim_{x ightarrow +infty}frac{1-(1-Q)^x}{1-(1-Q)}=frac{1}{Q}$

AC代码

#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
", ++kase, int(1/Q));
	}
}
原文地址:https://www.cnblogs.com/sahdsg/p/12787787.html