题目大意:
有 (n) 项任务,有一个数 (K)。每一项任务成功的概率是 (p_i)(这里与原题目不同,原题目是百分之 (p'_i),这里相当于 (p_i=frac{p'_i}{100})),成功后会使 (K) 加上 (a_i)。问至少成功 (l) 次且最后 (Kleq0) 的概率是多少。
数据范围:(0leq Kleq2000,0leq Lleq Nleq 200,-1leq a_ileq1000,0leq p_ileq100)。
正文:
这道题 (Kleq2000) 很搞人,但是我们发现其实 (K) 至多到 (200)。毕竟 (a_i) 最少是 (-1),就是最多加上 (n) 个 (-1) 才会对结果有影响。那么我们确定了 (K) 最终的范围:(-200leq Kleq200)。
搞定 (K) 以后,我们设 (f_{i,j,k}) 表示前 (i) 个任务成功了 (j) 个当前的 (K) 为 (k) 的概率。
得到转移方程:
[f_{i,j,k}=f_{i-1,j,k}cdot(1-p_i)+f_{i-1,j,k-a_i}cdot p_i
]
很明显,(f_{0,0,K}=1)。
代码:
double f[N][N][N * 2];
int a[N];
double p[N], ans;
int n, l, K;
int main()
{
scanf ("%d%d%d", &n, &l, &K);
for (int i = 1; i <= n; i++)
scanf ("%lf", &p[i]), p[i] /= 100.0;
for (int i = 1; i <= n; i++)
scanf ("%d", &a[i]), a[i] = a[i] > 200? 200: a[i];
f[0][0][K + 200] = 1;
for (int i = 1; i <= n; i++)
for (int j = 0; j <= i; j++)
for (int k = -200; k <= 200; k++)
f[i][j][k + 200] = j > 0? f[i - 1][j][k + 200] * (1.0 - p[i]) + f[i - 1][j - 1][k - a[i] + 200] * p[i]: f[i - 1][j][k + 200] * (1.0 - p[i]);
for (int i = l; i <= n; i++)
for (int k = 200; k <= 400; k++)
ans += f[n][i][k];
printf ("%.6lf", ans);
return 0;
}