传送门
强烈谴责:
对于懂全概率公式的人来说这是一道水题。
然而就是这群懂全概率公式的人写着一篇篇题解与代码不符的博客。连递推数组 f f f的下标含义都描述的完全错误,不是思路不同的问题,因为我照着与他们完全互斥的思路推出了与他们完全相同的公式,而照着他们的思路。。。麻烦懂了全概率之后再来写题解行吗。
更不用说什么"直接根据全概率公式可知"。。。连完备事件集都没有给出还全概率公式
以上写题解的方式就是不负责的表现
蒟蒻在经历了种种不负责任的题解洗礼之后终于推出了一个不用高深的全概率公式的理解方式。
思路:
根据乘法原理,每个生物的情况其实是一样的,所以只需要推出一只的情况然后
k
k
k次方就行了。
考虑我们现在知道了一只生物的家族在第
i
i
i天及之前完全死亡(包括一个后代都没有的请款),记为
f
i
f_i
fi,显然有
f
1
=
p
0
f_1=p_0
f1=p0,及第一只死亡的时候没有产生任何后代。
然后现在考虑我们知道 f i f_i fi,怎么求出 f i + 1 f_{i+1} fi+1,首先它没有任何后代的情况要计算,因为算的是第 i i i天及之前。
然后考虑他产生了某个数量 j j j的后代,概率为 p j p_j pj,那么它的家族要在第 i + 1 i+1 i+1天及之前完全死亡,对于后代来说就是在后代自己的第 i i i天及之前全部死亡。
所以 f i f_i fi可以理解为以一只生物开头的家族坚持不超过 i i i天的概率,那么对于后代来说,父亲的第 i + 1 i+1 i+1天其实就是它们的第 i i i天,所以可以直接用父亲的 f i f_i fi来计算。
那么对于第一只生物,有如下递推式 f i = ∑ j = 0 n − 1 p j × f i − 1 j f_i=\sum_{j=0}^{n-1}p_j\times f_{i-1}\text{ }^j fi=j=0∑n−1pj×fi−1 j
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
template<class T>
T quickpow(T a,int b){
T ans=1;
while(b){
if(b&1)ans*=a;
a=a*a;
b>>=1;
}
return ans;
}
int T,t;
double f[1005];
double p[1005];
signed main(){
scanf("%d",&T);
while(T--){
int n,k,m;
scanf("%d%d%d",&n,&k,&m);
for(int re i=0;i<n;++i)scanf("%lf",&p[i]);
f[1]=p[0];
for(int re i=2;i<=m;++i){
f[i]=0;
for(int re j=0;j<n;++j){
f[i]+=p[j]*quickpow(f[i-1],j);
}
}
printf("Case #%d: %.7lf\n",++t,quickpow(f[m],k));
}
return 0;
}