第一问是显然的, 把所有的权值加起来。
看着数据范围就知道是状压DP。
所以设$large f[S]$为已买状态为S的期望步数。
那么$large f[S] = sum f[S']*p[i] + (1 - sum p[i])*f[S]+1 $,因为有$large p[i]$的几率选到没选过的某一个, 有$large 1- sum p[i]$的几率选择之前选过的或者没有选到。
然后移项 $large f[S]=frac{sum p[i]*f[S']+1}{sum p[i]}$.
于是可以递推了。
复杂度$large O(2^{N})$
#include <iostream> #include <cstdio> using namespace std; inline int read() { int res=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define ll long long #define reg register int n; double p[25]; int w[25]; ll ans; int bin[25]; double f[1<<22]; int main() { bin[0] = 1;for (int i = 1 ; i <= 22 ; i ++) bin[i] = bin[i-1] << 1; n = read(); for (reg int i = 1 ; i <= n ; i ++) scanf("%lf", &p[i]), ans += (w[i] = read()); printf("%lld ", ans); for (reg int S = 1 ; S <= (1 << n) - 1 ; S ++) { double tot = 0; for (reg int i = 1 ; i <= n ; i ++) { if (S & bin[i-1]) f[S] += f[S-bin[i-1]] * p[i], tot += p[i]; } f[S] = (f[S] + 1) / tot; } printf("%.3lf ", f[(1<<n)-1]); return 0; }