题目描述
题解
首先普及一个知识点,每一件物品选到的概率是 p i p_i pi,则在所有物品里面至少选到一件的概率是: ∑ p i \sum p_i ∑pi.
然后就是很明显的概率状压了。
我们设 f [ i ] f[i] f[i]表示状态为i的期望次数。
则一定有: f [ i ] = ∑ j i n i f [ i 去 掉 j ] ∗ p j + ( 1 − ∑ j i n i p j ) ∗ f [ i ] + 1 f[i]=\sum_{j\ in\ i}f[i去掉j]*p_j+(1-\sum_{j\ in\ i} p_j)*f[i]+1 f[i]=j in i∑f[i去掉j]∗pj+(1−j in i∑pj)∗f[i]+1
移项以后就有: f [ i ] = ∑ j i n i f [ i 去 掉 j ] ∗ p j ∑ j i n i p j + 1 f[i]=\frac{\sum_{j\ in\ i}f[i去掉j]*p_j}{\sum_{j\ in\ i} p_j}+1 f[i]=∑j in ipj∑j in if[i去掉j]∗pj+1
代码如下:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 21;
int n, sum = 0;
int v[N];
double p[N], f[1<<N];
signed main(void)
{
freopen("gift.in","r",stdin);
freopen("gift.out","w",stdout);
cin>>n;
for (int i=1;i<=n;++i)
cin>>p[i]>>v[i],
sum += v[i];
cout<<sum<<endl;
for (int i=1;i<(1<<n);++i)
{
double sum = 0.000;
for (int j=1;j<=n;++j)
if (((i >> j-1) & 1) == 1)
{
f[i] += p[j]*f[i^(1<<j-1)];
sum += p[j];
}
f[i] = (f[i]+1)*1.0/sum;
}
printf("%.3lf",f[(1<<n)-1]);
return 0;
}
总结:
计算期望的时候,一个常见的套路就是上一部的期望乘上当前的概率+1.