codeforces 1153F Serval and Bonus Problem

思路

将原线段缩成1, 因为线段长度不影响结果
2n个点将线段分成了2n+1条线段, 我们有理由认为这 2 n + 1 2n+1 2n+1条子线段的期望等长。
证明:
第一条线段大于等于x的概率 ( 1 − x ) 2 n (1-x)^{2n} (1x)2n
对上式求导,得等于x的概率 2 n ( 1 − x ) 2 n − 1 2n(1-x)^{2n-1} 2n(1x)2n1
第一段的长度期望为 E 1 = 2 n ∫ 0 1 x ( 1 − x ) 2 n − 1 d x = 1 2 n + 1 E_{1}=2n\int^1_0 x(1-x)^{2n-1}dx=\frac{1}{2n+1} E1=2n01x(1x)2n1dx=2n+11
归纳一下,后面也必然相同

考虑dp, 自然想到dp[i][j]表示为第i个有j没匹配的方案数, 方案数考虑每条线段的顺序事先排好,然后前后匹配一下即可.
之前考虑用概率Wa了,因为每种转移往后的方案数不一定相等,及不是等概率的增删。

#include
using namespace std;

const int MAX_N = 4e3 + 5;
typedef long long ll;
ll dp[MAX_N][MAX_N];
ll r[MAX_N], f[MAX_N];
const ll mod = 998244353;
int n, k, l;

void init() {
	r[1] = 1; f[0] = 1;
	for (int i = 2; i < MAX_N; i++) r[i] = r[mod%i] * (mod - mod / i) % mod;
	for (int i = 1; i >= 1;
	}
	return res;
}
int main() {
	init();
	cin >> n >> k>>l;
	dp[0][0] = 1;
	for (int i = 1; i <=2*n; i++) {
		for (int j = 0; j <= min(n, i); j++) {
			dp[i][j] += dp[i - 1][j - 1] * val_select(i - 1, j - 1) % mod;
			dp[i][j] += dp[i - 1][j + 1] * val_remove(i - 1, j + 1) % mod;
		}
	}
	ll ans = 0;
	for (int i = 1; i <= 2 * n; i++) {
		for (int j = k; j <= n; j++) {
			ans = (ans + dp[i][j] * dp[2 * n - i][j] % mod*f[j]) % mod;
		}
	}
	ans = ans * r[2 * n + 1] % mod*l%mod * mod_r(dp[2*n][0])%mod;
	cout << ans << endl;
	//system("pause");
}

你可能感兴趣的:(ACM)