一.题目链接:
LightOJ-1408
二.题目大意:
每次投球有 p 的概率投空,若连续投中 k1 次 或 连续投空 k2 次,游戏结束.
求投球次数的期望.
三.分析:
f[i]: 已经连续投中 i 次,距离游戏结束还需投球次数的期望.
g[i]:已经连续投空 i 次,距离游戏结束还需投球次数的期望.
易得转移方程:
f[i] = (1 - p) * f[i + 1] + p * g[1] + 1.
g[i] = p * g[i + 1] + (1 - p) * f[1] + 1.
经简单迭代可得:
联立两式可得:
解出 f[1] 后回带即可得到 g[1].
最终答案 ans = qf[1] + pg[1] + 1.
四.代码实现:
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
double quick(double a, int b)
{
double sum = 1.0;
while(b)
{
if(b & 1) sum *= a;
a *= a;
b >>= 1;
}
return sum;
}
int main()
{
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ++ca)
{
double p; int k1, k2;
scanf("%lf %d %d", &p, &k1, &k2);
if(fabs(p - 0.0) < eps) printf("Case %d: %d\n", ca, k1);
else if(fabs(p - 1.0) < eps) printf("Case %d: %d\n", ca, k2);
else
{
double q = 1.0 - p;
double pk = quick(p, k2 - 1), qk = quick(q, k1 - 1);
double f1 = (1.0 - qk) * ((1.0 - pk) / q + 1.0 / p) / (1.0 - (1.0 - qk) * (1.0 - pk));
double g1 = (q * f1 + 1.0) * (1.0 - pk) / (1.0 - p);
double ans = q * f1 + p * g1 + 1.0;
printf("Case %d: %f\n", ca, ans);
}
}
return 0;
}