您的位置:首页 > 其它

FZU 2103 排列组合

2014-10-30 22:31 344 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: