「HAOI2015」按位或
解题思路 :
这类期望题一眼 ( ext{Min-Max}) 容斥,只需要稍微推一下如何求 (E(minS)) 即可。
[E(minS) = frac{1}{sum_{T cap S
eq emptyset} p_T} \
= frac{1}{1-sum_{T cap S = emptyset}p_T} \
= frac{1}{1-sum_{T cap (U-S) = T}p_T} \
= frac{1}{1-sum_{T subseteq (U-S)}p_T}
]
对 (p) 做莫比乌斯变换得到:
[p'_S=sum_{T subseteq S} p_T \
E(minS) = frac{1}{1-p'_{(U-S)}}
]
然后直接 ( ext{Min-Max}) 容斥就做完了,总复杂度 (O(n2^n))。
code
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 2000005;
const double eps = 1e-6;
double p[N], ans;
int cnt[N], n;
int main(){
read(n);
for(int i = 0; i < (1 << n); i++) scanf("%lf", &p[i]);
for(int i = 0; i < n; i++)
for(int s = 0; s < (1 << n); s++)
if((1 << i) & s) p[s] += p[s^(1<<i)], cnt[s]++;
for(int i = 0; i < n; i++)
if(1.0 - p[(1<<n)-(1<<i)-1] < eps) return puts("INF"), 0;
for(int s = 0; s < (1 << n); s++){
double res = 1.0 - p[(1<<n)-s-1];
if(res > eps) ans += (1.0 / res) * (cnt[s] & 1 ? 1.0 : -1.0);
}
printf("%.10lf", ans);
return 0;
}