LA 4661 重复元素的排列

题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2662

思想: 1 先把每个概率乘起来,然后乘以可充排列的种数。

             2 先一开始用(n1+n2+n3+...+nk)! / (n1! *n2! * n3!*...*nk!) 来算,sb了 因为用BigInteger太慢了~ 这个数是可以很大很大的, 50!呀。但是这个数可以拆成组合数的乘积: c[n1+n2+..+nk][n1] *c[n2+n3+..nk][n2] * c[n3+...nk][n3]*...c[nk][nk];      每次算出一个就乘那个double ,不用保存下来。

             3 算指数的时候,还有防止while死循环 只有大于0 才找指数。 

             4最后的指数可能是0 ,所以是 -1*count  不能把-号放在字符串里面

  

#include<iostream>
#include<map>
#include<cstdio>
#include<fstream>
using namespace std;
typedef long long inta;
inta c[60][60];

int main()
{

   for(int i=0;i<60;i++)
     for(int j=0;j<60;j++)
        c[i][j]=0;

   for(int i=0;i<60;i++)
      {c[i][0]=1;
       c[i][i]=1;
      }

   for(int i=1;i<60;i++)
      for(int j=1;j<i;j++)
         c[i][j]=c[i-1][j]+c[i-1][j-1];

  // ifstream cin("testdata.txt");


   int T;
    cin>>T;

   int index=0;
   while(T--)
   {
    index++;

      cout<<"Test Case #"<<index<<":"<<endl;

      int n;
      cin>>n;
      double *p =new double [n];
      for(int i=0;i<n;i++)
        cin>>p[i];

     int query;
     cin>>query;
     for(int i=0;i<query;i++)
     {
        map<int,int> m;
        int k;
        cin>>k;

        double doubleans=1;

       for(int j=0;j<k;j++)
       {
         int temp;
         cin>>temp;
         doubleans*=p[temp-1];

         m[temp]++;


       }
         map<int,int> :: iterator it=m.begin();
         for(;it!=m.end();it++)
        {
           doubleans*=c[k][it->second];
           k-=it->second;

        }
      // doubleans*=ans;


       int count=0;
       if(doubleans>0)
       {

       while(doubleans<1)
       {
          doubleans*=10;
          count++;
       }
       }

      printf("%.5f",doubleans);

     //  cout<<" x 10^-"<<count<<endl;

     cout<<" x 10^"<<-1*count<<endl;
     }

   }
}

   


posted @ 2013-08-07 00:58  814jingqi  阅读(130)  评论(0编辑  收藏  举报