Batting Practice LightOJ - 1408
连续击球,击不中的概率是 p,连续击中 k1 次时或连续 k2 次都没有击中时停止击球,问停止击球时的期望击球数。
设 f(x) 为已经连续击中 x 次后停止击球的期望击球数。
设 g(x) 为已经连续失击 x 次后停止击球的期望击球数。
则 f(k1)=g(k2)=0 ,对于 x≤k1:
f(x)f(x)+bf(x)bf(x)+bf(1)f(1)=(1−p)f(x+1)+pg(1)+1=(1−p)(f(x+1)+b)=(1−p)f(x+1)−pb=−g(1)−p1=(1−p)k1−x(f(k1)+b)=b(1−p)k1−x=b(1−p)k1−1−b=(g(1)+p1)(1−(1−p)k1−1)
对于 x≤k2:
g(x)g(x)+ag(x)ag(x)+ag(1)g(1)=pg(x+1)+(1−p)f(1)+1=p(g(x+1)+a)=pg(x+1)+a(p−1)=−f(1)−1−p1=pk2−x(g(k2)+a)=apk2−x=apk2−1−a=(f(1)+1−p1)(1−pk2−1)
然后解出来 f(1),g(1),如下:
f(1)f(1)(1−(1−pk2−1)(1−qk1−1))f(1)f(1)g(1)=((f(1)+1−p1)(1−pk2−1)+p1)(1−(1−p)k1−1)=((f(1)+q1)(1−pk2−1)+p1)(1−qk1−1)=q1(1−pk2−1)(1−qk1−1)+p1(1−qk1−1)=pq(1−pkqk)pkqkp+qqk=1−pkqkpkqk/q+qk/p=(f(1)+q1)pk=pq(1−pkqk)pkqkq+ppk=1−pkqkpkqk/p+pk/q
然后结果为 res=(1−p)f(1)+pg(1)+1
代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#define eps 1e-6
using namespace std;
int T,iCase,k1,k2;
double p,q,pk,qk,f1,g1;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%lf%d%d",&p,&k1,&k2);
q=1-p;
if(p<eps){
printf("Case %d: %d\n",++iCase,k1);
continue;
}
if(q<eps){
printf("Case %d: %d\n",++iCase,k2);
continue;
}
pk=1-pow(p,k2-1);qk=1-pow(q,k1-1);
f1=(pk*qk/q+qk/p)/(1-pk*qk);
g1=(pk*qk/p+pk/q)/(1-pk*qk);
printf("Case %d: %.8lf\n",++iCase,q*f1+p*g1+1);
}
return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200327083943319.png)