luogu P3175 [HAOI2015]按位或
阿新 • • 發佈:2019-01-18
include 要求 fabs 集合 puts put space while can ,也就是\(1-\sum_{s\subset ?_{S}T}P_s\),高位前綴和即可
傳送門
如果每個位置上的數字的意義是這個位置被加進集合的最早時間,那麽我們要求的就是集合中最大數的期望,使用Min-Max容斥,\(E(max(S))=\sum_{T\subset S}(-1)^{|T|+1}E(min(T))\),這裏的\(E(min(T))\)是集合中加進數字的期望時間,根據題意,加進一個集合數字概率為\(\sum_{s\cap T\ne\emptyset}P_s\),對應的期望,也就是\(E(min(T))=\frac{1}{\sum_{s\cap T\ne\emptyset}P_s}\)
但是\(\sum_{s\cap T\ne\emptyset}P_s\)不是很好求,可以轉化成\(1-\sum_{s\cap T=\emptyset}P_s\)
#include<bits/stdc++.h> #define LL long long #define il inline #define re register #define db double using namespace std; const int N=(1<<20)+10; il int rd() { int x=0,w=1;char ch=0; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } int n,nn; db p[N],ans,h[N]; int main() { n=rd(); nn=(1<<n)-1; int ff=0; for(int i=0;i<=nn;++i) { scanf("%lf",&p[i]); if(p[i]>1e-8) ff|=i; } if(ff^nn) return puts("INF"),0; for(int i=1;i<=nn;i<<=1) for(int j=0;j<=nn;++j) if((j&i)==i) p[j]+=p[j^i]; h[0]=1; for(int i=0;i<=nn;++i) { h[i]=-h[i^(i&(-i))]; if(fabs(1-p[nn^i])>1e-8)ans+=h[i]*1/(1-p[nn^i]); } printf("%.8lf\n",ans); return 0; }
luogu P3175 [HAOI2015]按位或