您的位置:首页 > 其它

FZU 2103 Bin & Jing in wonderland 排列求概率

2014-02-21 14:59 288 查看
原题:



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

42 3 30.3 0.71 1 12 3 30.3 0.71 1 22 3 30.3 0.71 2 22 3 30.3 0.72 2 2



Sample Output

0.027000

0.189000

0.441000

0.343000



Source

“高教社杯”第三届福建省大学生程序设计竞赛

题意+题解:

题目是说 有N个数,选1--N的概率分别是p[1]---p
, 已知选K次,已知其中最大的R个数是 num[1]---num[r],求能得到这个结果的概率

算是一道水题把,但是当时写了好久都没过,刚开始用排列做的,发现A(26,52)的值已经超longlong,所以得用组合。还有就是剩余的K-R个点中有最小数的情况我没考虑好导致WA了。

首先计算出给出的这R个数,在1--N中出现的次数,即为T[i],找出其中非最小数的其他数,ans_p = ans_p * (p[i]^T[i]) * C(T[i],left); 其中C(T[i],left)是k=T[i],n=left的组合数。

其次,对于R个数中的最小值,在剩余的较小的K-R个数中也都可能存在,故准备暴力枚举所有可能的最小值的个数,至于其他的小于最小值的点,可以合并成一个新点,新点的概率为组成其点的概率和。

具体见程序。

代码:

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
long long C(int n,int k)
{
int i;
long long ans=1;
for ( i = 1; i <=k ; i++)
{
ans*=  (n-i+1);
ans/=i;
}
return ans;
}
double my_pow(double x,int n)
{
double ans=1;
while (n--)
{
ans*=x;
}
return ans;
}
int main()
{
int t,i;
int n,k,r;
int list[28];
int min_num;
int times[25];
double p[25];
double ans;
double rest_p;
double temp_p;
long long  temp;
int rest_time;
int temp_k;
scanf("%d",&t);
while (t--)
{
memset(times,0,sizeof(times));
ans=1;
min_num=99;
rest_p=0;
temp=1;
temp_p=0;
scanf("%d%d%d",&n,&k,&r);
for ( i = 1; i <=n ; i++)
{
scanf("%lf",&p[i]);
}
for ( i = 1; i <=r ; i++)
{
scanf("%d",&list[i]);
if(list[i]<min_num)min_num=list[i];
times[list[i]]++;
}
temp_k=k;
for ( i = 1; i <=n ; i++)
{
if(i!=min_num)
{
ans *= (my_pow(p[i],times[i]) * C(temp_k,times[i]));
temp_k-=times[i];
}
}
for ( i = 1; i < min_num; i++)
{
rest_p+=p[i];
}
for ( i = 0; i <= k-r ; i++)//i表示剩余的可选k-r个点中出现最小值的个数
{
rest_time = (k-r-i);
temp_p +=   ( (my_pow(p[min_num],times[min_num]+i) * C(k-r+times[min_num],times[min_num]+i)) * (my_pow(rest_p,rest_time) * C(k-r-i,rest_time)) );
}
ans*=temp_p;
printf("%.6lf\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐