题意:你每天晚上玩游戏,第一把赢了就去睡觉,输了继续。你每一把赢的概率是p,当你赢的比例严格大于p时,才会去睡觉。但是你一个晚上最多玩n把游戏,如果哪天获胜比例一直没有大于p,你以后再也不玩了。求玩游戏天数的期望。
思路:先求出一个晚上赢的比例一直没有超过p的概率P,方法是概率dp,一盘一盘向后推,超过比例则跳出。答案直接就是1/P。。为什么,回忆一下概率论学过的内容,这不就是几何分布吗。。做一件事(每次独立)成功概率是P,第一次做成时做的次数的期望就是1/P。还有一点要注意的,到底怎么判断赢的比例有没有超过p,我是从白书上学到的,方法见代码。
做了这题收获还是不小的:
1.能避免使用浮点数的时候,就不要使用,毕竟容易丢失精度。
2.数学非常重要。能用数学方法算出的值往往比递推n次要精确,毕竟n不能达到极限。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <assert.h>
#include <set>
#include <ctype.h>
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
using namespace std;
double dp[110][110];
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
int a,b;
char c;
double p;
cin>>a>>c>>b;
p=(double)a/b;
int n;
cin>>n;
//init
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)dp[i][j]=0.0;
dp[1][0]=1.0-p;
for(int i=2;i<=n;i++){
for(int j=0;j<=n;j++){
dp[i][j]+=dp[i-1][j]*(1.0-p);
if((j+1)*b>a*i)break;
dp[i][j+1]=dp[i-1][j]*p;
}
}
double plose=0.0;
for(int i=0;i<=n;i++){
plose+=dp[n][i];
}
printf("Case #%d: %d\n",cas,(int)(1.0/plose));
}
return 0;
}