【luogu CF1153F】Serval and Bonus Problem(期望)(DP)
Serval and Bonus Problem
题目链接:luogu CF1153F
题目大意
长度为 l 的线段,有 n 个区间端点随机分布,然后问你期望有多少长度被至少 k 个区间覆盖。
思路
首先这种随机分布的期望题考虑也把随机的时间弄成一个平均分布。
在这里就是我们可以理解为这 \(2n\) 个端点是均匀分布在 \(l\) 上的,那每段长度就是 \(\dfrac{l}{2n+1}\)。
然后我们就可以考虑 DP,设 \(f_{i,j}\) 为 \(i\) 个端点,当前有 \(j\) 个左端点没有匹配。
那没有匹配说明要延伸过去,那只要延伸过去的数量大于等于 \(k\),就说明这个段是贡献的。
然后我们考虑每个位置放左端点还是右端点,注意如果是右端点你会选跟哪个左端点,所以要乘上 \(j\)。
然后你考虑怎么计算答案,你前面保证了这个左端点,那右端点你也应该要保证吧。
那左右端点其实是一样的,所以你可以直接用 DP 的值,就是两个乘起来,然后左右端点匹配是一个阶乘。
然后你前面算的是方案你要除总方案才是概率,然后总方案是 \(f_{2n,0}\)。
然后就可以啦。
代码
#include<cstdio>
#define ll long long
#define mo 998244353
using namespace std;
const int N = 2005;
int n, k, l;
ll f[N << 1][N], jc[N];
ll ksm(ll x, ll y) {
ll re = 1;
while (y) {
if (y & 1) re = re * x % mo;
x = x * x % mo; y >>= 1;
}
return re;
}
ll clac(int n, int k) {
f[0][0] = 1; ll ans = 0;
for (int i = 0; i < 2 * n; i++) {
for (int j = 0; j <= i && j <= n; j++) {
(f[i + 1][j + 1] += f[i][j]) %= mo;
if (j) (f[i + 1][j - 1] += f[i][j] * j % mo) %= mo;
}
}
for (int i = 1; i <= 2 * n; i++)
for (int j = k; j <= n; j++)
(ans += f[i][j] * f[2 * n - i][j] % mo * jc[j]) %= mo;
return ans * ksm(f[2 * n][0], mo - 2) % mo;
}
int main() {
scanf("%d %d %d", &n, &k, &l); l = l * ksm(2 * n + 1, mo - 2) % mo;
jc[0] = 1; for (int i = 1; i <= n; i++) jc[i] = jc[i - 1] * i % mo;
printf("%lld", clac(n, k) * l % mo);
return 0;
}

浙公网安备 33010602011771号