呵呵,我暴力WA了
这个题充分考验了大家对数学的理解(麦蒙大多在胡诌)
但是确实如此啊。
看数据范围想状压。(我额嗯嗯想到暴力?)
然后设出一个可爱的$dp$式(主语当然不是我,是出题人大佬)
$f_s$表示二进制组昂态(状态)为$s$时的期望。
那么我们可以从$s'$转移过来,其中$s' or\ s = s$或$s' and\ s =s$($and$和$or$均为位运算)(内两个式子是等效的)
那么有:
$f_s= \sum\limits_{i=1}^N p_i \times f_{s'}+(1-\sum \limits_{i=1}^N p_i) \times f_s +1$
真是恐怖,$f_s$转移需要自己~
但是表慌,数学老师可以拯救你,哒哒哒
移项。式子变为:
$\begin{array}{lcl}0 & = & \sum \limits_{i=1}^N p_i \times f_{s'}-f_s \times \sum \limits_{i=1}^N p_i +1\\f_s & = & \frac{\sum \limits_{i=1}^N p_i \times f_{s'}+1}{\sum \limits_{i=1}^N p_i}\end{array}$
还是比较简单的。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 //#include "debug.h" 6 7 #define N 22 8 using namespace std; 9 int n; 10 double p[N]; 11 long long val,dat; 12 double dp[(1<<20)+20]; 13 int main(){ 14 scanf("%d",&n); 15 for (int i=1;i<=n;i++){ 16 scanf("%lf%lld",&p[i],&dat); 17 val=val+dat; 18 } 19 cout<<val<<endl; 20 double ons=0,sums=0; 21 for (int s=0;s<1<<n;s++){ 22 ons=sums=0; 23 for (int i=1;i<=n;i++){ 24 if (s&(1<<(i-1))){ 25 ons+=dp[s^(1<<(i-1))]*p[i];//cout<<bin(s,n)<<"<<"<<bin(s^(1<<(i-1)),n)<<endl; 26 sums+=p[i];//cout<<sums<<endl; 27 } 28 }//cout<<"O:"<<ons<<" S:"<<sums<<endl; 29 if(sums==0){ 30 // cout<<"T0T"<<NL; 31 continue; 32 } 33 dp[s]=(ons+1.0)/sums; 34 } 35 // pour(dp,1,1<<n,10,"Dp"); 36 printf("%.3lf\n",dp[(1<<n)-1]); 37 return 0; 38 }