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