题目大意:刚开始有一个数$x=0$,每秒钟有一个数$yin[0,2^n)(nleqslant20)$按一定概率随机出现,数$i$的概率为$p_i$,保证$sumlimits_{i=0}^{2^n-1}p_i=1$。然后$x o x|y$,问期望多少时间后,$x=2^n-1$
题解:$Min-Max$容斥
$$
max(S)=sumlimits_{Tsubseteq S}(-1)^{|T|+1}min(T)\
min(S)=sumlimits_{Tsubseteq S}(-1)^{|T|+1}max(T)
$$
而且,它在期望下成立,即:
$$
E(max(S))=sumlimits_{Tsubseteq S}(-1)^{|T|+1}E(min(T))\
E(min(S))=sumlimits_{Tsubseteq S}(-1)^{|T|+1}E(max(T))
$$
这道题相当于求$E(max(S))$,也就是说,现在需要求$E(min(S))$。令$s(S)$表示随机出来的数$yin S$的概率,即$sumlimits_{yin S}p_y$,这可以用$FWT$解决。
求$E(min(S))$,就枚举选了多少次数与$S$都没有交
$$
egin{align*}
E(min(S))&=sumlimits_{i=0}^{infty}s(ar S)^i(i+1)(1-s(ar S))\
&=(1-s(ar S))dfrac1{(1-s(ar S))^2}\
&=dfrac1{1-s(ar S)}
end{align*}
$$
然后$Min-Max$容斥一下就好了
卡点:无
C++ Code:
#include <algorithm> #include <cstdio> #define N 1048576 | 3 int lim, U; void FWT(double *A) { for (int mid = 1; mid < lim; mid <<= 1) for (int i = 0; i < lim; i += mid << 1) for (int j = 0; j < mid; ++j) A[i + j + mid] += A[i + j]; } int n; double p[N], s[N], f[N]; int main() { scanf("%d", &n); lim = 1 << n, U = lim - 1; for (int i = 0; i < lim; ++i) scanf("%lf", p + i); std::copy(p, p + lim, s); FWT(s); for (int i = 0; i < lim - 1; ++i) if (s[i] == 1) { puts("INF"); return 0; } for (int i = 1; i < lim; ++i) f[i] = 1 / (1. - s[U ^ i]); double ans = 0; for (int i = 1; i < lim; ++i) { if (__builtin_popcount(i) & 1) ans += f[i]; else ans -= f[i]; } printf("%.6lf ", ans); return 0; }