假设有卡片 1, 2, 3 ,用 F(S) 表示在已拿到 S 集合表示的卡片时还需要购买的卡片期望值
答案为 F(Ø) , F(U) = 0 (U 是全集,就是已得到所有卡片)
分别考虑每次买卡时 1.得到新卡 2.得到重复的卡片或没有得到卡片 的情况
比如 F({1}) = F({1, 2, 3}) * (p2 + p3) + F({1}) * (1 - p2 - p3) + 1
情况1 情况2
严谨一点就是
F(S) = F({S υ A}) * ∑pi + F(S) * (1 - ∑pi) + 1
其中 A 是没有得到的卡片, pi 是给出的得到这些卡片的概率
得到 F(S) = F({S υ A}) + 1 / ∑pi
考虑到精度问题,可以变成
F(S) = (∑pi * F({S υ A}) + 1) / ∑pi
顺序枚举 S υ A 和 A,这道题很适合二进制子集构造法(全集 U = 1<<N 最大才 1024*1024 ,数组开得下),当然写搜索也可以过。
1 #include <stdio.h> 2 3 typedef long long LL; 4 5 const int _N = 22; 6 7 double f[1<<_N], p[_N]; 8 9 int main() 10 { 11 LL n, FULL, i, j; 12 double sump; 13 scanf("%lld", &n); 14 for (i = 1; i <= n; ++i) 15 scanf("%lf", &p[i]); 16 f[FULL = (1<<n) - 1] = 0; 17 for (i = FULL-1; i >= 0; --i) { 18 f[i] = 1, sump = 0; 19 for (j = 0; j < n; ++j) { 20 if ((i>>j) & 1 ^ 1) 21 f[i] += f[i | (1<<j)] * p[j+1], sump += p[j+1]; 22 } 23 f[i] /= sump; 24 } 25 printf("%.6lf ", f[0]); 26 return 0; 27 }
题目:NKOJ2127
P2127【概率】搜集卡片 | |
|
问题描述
童年时代,你是否热衷于搜集零食里的卡片呢?比如你集齐了108张水浒英雄的卡片,你会感到非常有成就感,而且还可以去兑换奖品。
作为一个聪明的小孩,你注意到如果你要赢得奖品,你必须买很多很多的零食才能搜集齐卡片。要赢得奖品,你估计要买多少袋零食才能成功?
输入格式
第一行,一个整数N(1 <= N <= 20), 表示总共有N种不同的卡片。
第二行,N个空格间隔的实数p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), 表示零食袋中每种卡片出现的概率。
注意:一包零食中最多有一张卡片,也可能一张都没有。
输出格式
一个实数,表示你计算的结果,保留6位小数
样例输入
2
0.1 0.4
样例输出
10.500000