min-max 容斥入门题。
相当于求每个位置的期望次数的最大值,用 min-max 容斥得到:
考虑如何求 $\displaystyle E(\min_{i\in S}t_i)$,考虑期望的离散计算方式,设 $f(S)$ 表示选中不覆盖 $S$ 中任意位置的概率,有 $\displaystyle E(\min_{i\in S} t_i)=(1-f(S))\cdot\sum_{k=1}k\cdot f(S)^{k-1}$。后面一部分推一下:
于是得到:
但其实上面推的式子是完全没有必要的,补集转换就可以得到上式。
对于 $f(S)$ 可以用 FMT 求出,总时间复杂度为 $\mathcal O(n2^n)$。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #include<iostream> #include<cstdio> #define popcnt __builtin_popcount using namespace std; const int N=21,M=1<<N; template<class T> inline void read(T &x) { x=0;int f=0; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); if(f)x=~x+1; } template<class T,class ...T1> inline void read(T &x,T1 &...x1) { read(x),read(x1...); } int n,tot; int sum; double ans,f[M]; inline void FMT() { for(int i=0;i<n;i++) for(int j=0;j<tot;j++) if(j>>i&1) f[j]+=f[j^(1<<i)]; } int main() { read(n);tot=1<<n; for(int i=0;i<tot;i++)scanf("%lf",&f[i]),sum|=(f[i]!=0)?i:0; if(sum!=tot-1)return puts("INF"),0; FMT(); for(int i=1;i<tot;i++)ans+=(popcnt(i)&1?1:-1)*(1.0/(1-f[tot-1^i])); printf("%.10lf",ans); return 0; }
|