传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4008
【题解】
我们把牌看成人吧好说明qwq
f[i,j]表示第i个人得到了j次机会的概率。
f[i,j]=f[i-1,j]*(1-p[i-1])^j+f[i-1,j+1]*(1-(1-p[i-1])^(j+1))
(前一个人得到了j次机会,都没有把握住;前一个人得到了j+1次机会,把握住了一次)
明显可以dp。
统计答案的话,就是
ΣΣf[i,j]*(1-(1-p[i])^j)*d[i]
(考虑每个人得到机会的概率,他们只要一次把握住就能造成伤害)
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 310; # define RG register # define ST static int n, r; ld p[M], d[M]; ld g[M][M], f[M][M]; int main() { int T; scanf("%d", &T); while(T--) { memset(f, 0, sizeof f); scanf("%d%d", &n, &r); p[0] = 0.0; for (int i=1; i<=n; ++i) { double pd, pe; scanf("%lf%lf", &pd, &pe); p[i] = (ld)pd; d[i] = (ld)pe; } for (int i=0; i<=n; ++i) { g[i][0] = 1.0; for (int j=1; j<=r; ++j) g[i][j] = g[i][j-1]*(1.0-p[i]); } // 第i个人得到了j次机会 ld ans = 0.0; f[0][r] = 1.0; for (int i=1; i<=n; ++i) for (int j=1; j<=r; ++j) { f[i][j] = f[i-1][j]*g[i-1][j] + f[i-1][j+1]*(1.0-g[i-1][j+1]); ans = ans + f[i][j]*(1-g[i][j])*(ld)d[i]; } printf("%.10lf ", (double)ans); } return 0; }