Problem Description
Bin has a dream that he and Jing are both in a wonderland full of beautiful gifts. Bin wants to choose some gifts for Jing to get in her good graces.
There are N different gifts in the wonderland, with ID from 1 to N, and all kinds of these gifts have infinite duplicates. Each time, Bin shouts loudly, “I love Jing”, and then the wonderland random drop a gift in front of Bin. The dropping probability for
gift i (1≤i≤N) is P(i). Of cause, P(1)+P(2)+…+P(N)=1. Bin finds that the gifts with the higher ID are better. Bin shouts k times and selects r best gifts finally.
That is, firstly Bin gets k gifts, then sorts all these gifts according to their ID, and picks up the largest r gifts at last. Now, if given the final list of the r largest gifts, can you help Bin find out the probability of the list?
Input
The first line of the input contains an integer T (T≤2,000), indicating number of test cases.
For each test cast, the first line contains 3 integers N, k and r (1≤N≤20, 1≤k≤52, 1≤r≤min(k,25)) as the description above. In the second line, there are N positive float numbers indicates the probability of each gift. There are at most 3 digits after the decimal
point. The third line has r integers ranging from 1 to N indicates the finally list of the r best gifts’ ID.
Output
For each case, output a float number with 6 digits after the decimal points, which indicates the probability of the final list.
Sample Input
4
2 3 3
0.3 0.7
1 1 1
2 3 3
0.3 0.7
1 1 2
2 3 3
0.3 0.7
1 2 2
2 3 3
0.3 0.7
2 2 2
Sample Output
0.027000
0.189000
0.441000
0.343000
思路:
k>r时,多余的k不能掉落比最小值编号小的礼物,所以记录最小值以及小于最小值的记录。然后按每个编号的数量排列组合。
代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
int N,K,R;
int num[100];
double p[100];
double C(int n,int m)
{
double sum=1.0;
int i,j;
for(i=m; i>=m-n+1; i--)
{
sum*=1.0*i;
}
for(j=1; j<=n; j++)
{
sum/=(1.0*j);
}
return sum;
}
int min(int a,int b)
{
if(a>b)
return b;
else
return a;
}
int main()
{
int t,Minid;
int i,j,rem,k;
double pp,p1,pro,ans;
scanf("%d",&t);
while(t--)
{
Minid=6666666;
scanf("%d %d %d",&N,&K,&R);
memset(num,0,sizeof(num));
for(i=1; i<=N; i++)
{
scanf("%lf",&p[i]);
}
for(i=1; i<=R; i++)
{
int temp;
scanf("%d",&temp);
num[temp]++;
Minid=min(Minid,temp);
}
k=K;
pro=0;
for(i=1; i<Minid; i++)
{
pro+=p[i];
}
ans=0;
for(j=0; j<=K-R; j++)
{
p1=1.0;
num[Minid]+=j;
k=K;
for(i=1; i<=N; i++)
{
if(num[i])
{
p1=p1*C(num[i],k)*pow(p[i],num[i]);
k-=num[i];
}
}
pp=p1;
rem=K-R-j;
//剩下的次数只能掉落小于等于最小值的,仍要计算概率 while(rem>0)
{
pp*=pro;
rem--;
}
ans+=pp;
num[Minid]-=j;
}
printf("%.6f\n",ans);
}
return 0;
}
本文介绍了一个有趣的概率问题:在一个充满礼物的仙境中,主人公Bin通过喊出特定口号获得礼物,并从中挑选最好的几件送给Jing。文章详细阐述了如何计算在已知最终挑选的礼物列表情况下,这些礼物被选中的概率。
1072

被折叠的 条评论
为什么被折叠?



