[期望] [dp] CF1153F Serval and Bonus Problem
posted on 2024-10-01 13:16:51 | under | source
注意一下,本题不要求一个区间左端点小于右端点。
\(n\) 个区间共 \(2n\) 个点,将原线段分为 \(2n+1\) 个小线段。那么题目要求:\(ans=\sum\limits_{submit} E([cnt\ge k]len)\),\(cnt\) 是该线段被覆盖次数,\(len\) 是该线段长度。
注意到 \(cnt\) 与 \(len\) 无关,只取决于 \(2n\) 个点的相对位置。所以 \(ans=\sum E([cnt\ge k])E(len)\),而 \(E(len)=\frac l{2n+1}\),故 \(ans=\frac l{2n+1}\sum E([cnt\ge k])\),求这个西格玛就好。
单条线段的不好计算,所以直接计算 \(E(\sum [cnt\ge k])\),也就是所有情况中被至少 \(k\) 个区间覆盖的线段个数之和 \(cntS\),再除以总方案数。这个总方案数就是 \((2n)!\)。
然后 \(cntS\) 可以 dp 求出,不妨假定选择一条线段 \(X\),记 \(f_{i,j,0/1}\) 表示已确定前 \(i\) 个点,有 \(j\) 个左端点继续向右延伸,\(X\) 的位置是否确定的方案数。\(cntS=f_{2n,0,1}\)?但是我们这样 dp 相当于扫描线,也就是强制区间左端点从小到大,故 \(cntS=f_{2n,0,1}\times n!2^n\)。
复杂度 \(O(n^2)\)。
小插曲
一开始我想强制钦定左右端点大小关系、强制选择区间的顺序必须从小到大。这应该是没有问题的,因为上述两点都和所求期望没有任何关系。结果在计算总方案时,误以为是卡特兰数,实际上是多重排列,然后调了好久。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ADD(a, b) a = (a + b) % mod
const int N = 4e3 + 5, mod = 998244353;
int n, l, K, f[N][N][2], jc[N], p;
inline int qstp(int a, int k) {int res = 1; for(; k; a = a * a % mod, k >>= 1) if(k & 1) res = res * a % mod; return res;}
inline int C(int n, int m) {return jc[n] * qstp(jc[n - m], mod - 2) % mod * qstp(jc[m], mod - 2) % mod;}
signed main(){
jc[0] = 1; for(int i = 1; i < N; ++i) jc[i] = jc[i - 1] * i % mod;
cin >> n >> K >> l;
f[1][1][0] = 1;
for(int i = 1; i < 2 * n; ++i)
for(int j = 0; j <= n; ++j)
for(int k = 0; k < 2; ++k){
ADD(f[i + 1][j + 1][k], f[i][j][k]);
ADD(f[i + 1][j - 1][k], f[i][j][k] * j % mod);
if(!k && j >= K){
ADD(f[i + 1][j + 1][1], f[i][j][k]);
ADD(f[i + 1][j - 1][1], f[i][j][k] * j % mod);
}
}
cout << f[2 * n][0][1] * qstp(2, n) % mod * jc[n] % mod * qstp(jc[2 * n], mod - 2) % mod * l % mod * qstp(2 * n + 1, mod - 2) % mod;
return 0;
}

浙公网安备 33010602011771号