Boom!UUZ发飙了。参加ACM的培训本应该有n个人,今天却只来了那么一点点。已知每个学生能来上课的概率为Pi(1≤i≤n),当上课人数少于k时,UUZ会发飙,一旦UUZ发飙,那么以后的课(包括这节课)就都不上了,而如果不发飙,则UUZ还会开下一节课。那么,UUZ能为大家开课的期望大约是多少堂呢?精确到0.1就可以了。
标签:
Boom!UUZ发飙了。参加ACM的培训本应该有n个人,今天却只来了那么一点点。已知每个学生能来上课的概率为Pi(1≤i≤n),当上课人数少于k时,UUZ会发飙,一旦UUZ发飙,那么以后的课(包括这节课)就都不上了,而如果不发飙,则UUZ还会开下一节课。那么,UUZ能为大家开课的期望大约是多少堂呢?精确到0.1就可以了。
有多组输入数据,第一行为一个数字T,代表有T组输入数据 (0<T≤10)。
接下来为T组数据。
每组数据的第一行为两个整数n和k,其中,1≤n≤20,1≤k≤n.
接下来的一行有n个整数1位小数(大于0小于1),表示这n个学生来上课的概率。
对于每组数据,在一行上输出一个实数,表示UUZ上课的期望值。
只要答案的相对误差在10-6以内,或绝对误差在0.1以内,都判为正确。
1
3 1
0.1 0.1 0.1
0.4
设dp[i][j]表示前i个人中有j个人来上课的概率,初始:dp[0][0]=0;
状态转移方程为:dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i];
计算n个人中来上课的人数大于等于k时的概率为sum
则可求的上课天数的期望为:sum+sum^2+…+sum^x,(x→∞)
等比数列求和得:sum/(1-sum)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,k;
double p[25];
long double dp[25][25],sum;//dp[i][j]表示前i个人中有j个人来上课的概率
int main() {
int T;
scanf("%d",&T);
while(T-->0) {
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i) {
scanf("%lf",p+i);
}
dp[0][0]=1;
for(int i=1;i<=n;++i) {
for(int j=0;j<i;++j) {
dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i];
}
dp[i][i]=dp[i-1][i-1]*p[i];
}
sum=0;//sum表示n个人中来上课的人数大于等于k时的概率
for(int i=k;i<=n;++i) {
sum+=dp[n][i];
}
printf("%.2lf\n",double(sum/(1-sum)));
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/idealism_xxm/article/details/51345525