1043: Boooooom
时间限制: 1 Sec 内存限制: 128 MB Special Judge
http://acm.xidian.edu.cn/problem.php?id=1043
题目描述
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; }
时间: 2024-10-12 10:00:02