FZU 2103 Bin & Jing in wonderland (组合+概率)

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2103

题意:n个面的色子,出现第i个面的概率为pi。将该色子掷K次,给出K次中前r大的数字。求这种情况出现的概率。

思路:设f[i][j]表示i个数字最大数字为j的概率。这个很容易得到。设Min为前r大的数字中最小的数字。接着就是枚举K-r中Min出现了多少次,设为t。这样我们就能计算出r+t个数字的概率,就是排列组合的问题,再乘以f[K-r-t][Min-1]即可。

 #include <iostream>

 #include <stdio.h>

 #include <string.h>

 #include <cmath>

 #define max(x,y) ((x)>(y)?(x):(y))

 using namespace std;

 

 

 int C;

 int n,K,r,a[30],b[30],aNum;

 double f[55][55],p[25],c[55],cc[55][55];

 

 void init()

 {

     c[0]=1;

     int i,j;

     for(i=1;i<55;i++) c[i]=c[i-1]*i;

     for(i=1;i<=52;i++)

     {

         cc[i][0]=cc[i][i]=1;

         for(j=1;j<i;j++) cc[i][j]=cc[i-1][j]+cc[i-1][j-1];

     }

 }

 

 void cal(int x,int t)

 {

     int i,j,k;

     memset(f,0,sizeof(f));

     for(i=0;i<=t;i++) f[0][i]=1,f[1][i]=p[i];

     for(i=1;i<x;i++)

     {

         for(j=1;j<=t;j++) for(k=1;k<=t;k++)

         {

             f[i+1][max(j,k)]+=f[i][j]*p[k];

         }

     }

     for(i=1;i<=x;i++)

     {

         f[i][0]=0;

         for(j=1;j<=t;j++) f[i][j]+=f[i][j-1];

     }

 }

 

 void Add(int x)

 {

     int i;

     for(i=1;i<=aNum;i++) if(a[i]==x)

     {

         b[i]++;

         return;

     }

     aNum++;

     a[aNum]=x;

     b[aNum]=1;

 }

 

 double cal1(int x)

 {

     double ans=log(c[r+x]);

     int i;

     for(i=1;i<=aNum;i++) ans-=log(c[b[i]]);

     return ans;

 }

 

 int main()

 {

     init();

     for(scanf("%d",&C);C--;)

     {

         scanf("%d%d%d",&n,&K,&r);

         int i,j;

         for(i=1;i<=n;i++)  scanf("%lf",&p[i]);

         double temp=0;

         int Min=n;

         aNum=0;

         for(i=1;i<=r;i++)

         {

             scanf("%d",&j);

             temp+=log(p[j]);

             if(j<Min) Min=j;

             Add(j);

         }

         cal(K-r,Min);

         double ans=0;

         for(i=0;i<=K-r;i++)

         {

             ans+=exp(log(cc[K][r+i])+temp+cal1(i)+log(f[K-r-i][Min-1]));

             Add(Min);

             temp+=log(p[Min]);

         }

         printf("%.6lf\n",ans);

     }

     return 0;

 }

  

你可能感兴趣的:(in)