思想: 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;
}
}
}