Description
小 K 不慎被 LL **了,*程度深到他甚至想要从亚瑟王*中脱坑。
Input
输入文件的第一行包含一个整数 T,代表测试数据组数。
Output
对于每组数据,输出一行,包含一个实数,为这套卡牌在这一局游戏中造成的
Sample Input
3 2
0.5000 2
0.3000 3
0.9000 1
Sample Output
HINT
一共有 13 种可能的情况:
题解
利用期望的线性性 $E(x+y) = E(x)+E(y)$ 可知,这题我们可以先求出每张牌的打出概率 $fp_i$ ,然后就可以得出 $$ans = \sum_{i = 1}^n fp_i*d_i$$
这道题需要用到的一个公式:
在不考虑其他牌的前提下,若一张牌一轮打出的概率为 $p$ ,则在 $r$ 轮中打出这张牌的概率为: $$1-(1-p)^r$$
简要证明:
记要求的总概率为 $P$ ,显然
\begin{aligned}
P &= p+p*(1-p)+p*(1-p)^2+…+p*(1-p)^{r-1} \\
& = \frac{p*(1-(1-p)^r)}{1-(1-p)}\\
& = 1-(1-p)^r
\end{aligned}
另外我们发现,单独考虑每张牌的概率的时候,影响其的只有他前面选了几张。
我们不妨记一个辅助数组 $f_{i, j}$ 为总 $r$ 轮后前 $i$ 张牌中选中了 $j$ 张牌的概率。
容易发现: $$fp_i = \sum_{j = 0}^n f_{i-1, j}*(1-(1-p_i)^{r-j})$$
现在我们就是考虑 $f_{i, j}$ 如何转移。
第一种, $f_{i, j}$ 从 $f_{i-1, j}$ 转移过来,即第 $i$ 张牌最终没有选,始终不选第 $i$ 张牌的概率是 $(1-p_i)^{r-j}$
$$f_{i, j} += f_{i-1, j}*(1-p_i)^{r-j}(i>0)$$
第二种,当 $j>0$ 时, $f_{i, j}$ 可以从 $f_{i-1, j-1}$ 转移过来,表示最终选择了第 $i$ 张牌
这时候,有 $j-1$ 轮没有考虑到第 $i$ 张牌,所以考虑到第 $i$ 张牌的轮数是 $r-j+1$ ,最终选择的概率为 $1-(1-p_i)^{r-j+1}$
$$ f_{i, j} += f_{i-1, j-1}*(1-(1-p_i)^{r-j+1})(i>0,j>0)$$
总时间复杂度 $O(Tnr)$ 。
//It is made by Awson on 2018.1.2
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define LD long double
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = ; int n, r;
LD p[N+], d[N+];
LD pre[N+][N+], f[N+][N+], fp[N+]; void work() {
scanf("%d%d", &n, &r);
for (int i = ; i <= n; i++) scanf("%Lf%Lf", &p[i], &d[i]), pre[i][] = ;
for (int i = ; i <= n; i++) for (int j = ; j <= r; j++) pre[i][j] = pre[i][j-]*(-p[i]);
memset(f, , sizeof(f)); memset(fp, , sizeof(fp));
f[][] = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= r; j++) {
fp[i] += f[i-][j]*(-pre[i][r-j]);
f[i][j] += f[i-][j]*pre[i][r-j];
if (j > ) f[i][j] += f[i-][j-]*(-pre[i][r-j+]);
}
LD ans = ;
for (int i = ; i <= n; i++) ans += d[i]*fp[i];
printf("%Lf\n", ans);
}
int main() {
int t; cin >> t;
while (t--) work();
return ;
}