【HDU 6377】度度熊看球赛

题意:
有一排\(2 \cdot n\)个位置,一共有\(n\)对情侣要入座,当有\(x\)对情侣相邻,那么它们产生的喧闹值为\(D^x\),问情侣随机入座产生的喧闹值的期望。

思路:
考虑\(f[i][j]\)表示到第\(2i\)个位置,有\(j\)对情侣相邻的方案数。

  • 将情侣看成一个点进行插入:
    • \(j - 1\)转移过来,那么插入的地方为非情侣之间的空隙,空隙数量为\(2(i - 1) + 1 - (j - 1)\)
    • \(j\)转移过来,那么插入的地方为情侣之间的空隙,空隙数量为\(j\)
  • 将情侣看成两个点进行插入:
    • \(j\)转移过来,那么插入的两个点为非情侣之间的空隙,方案数为\((2(i - 1) + 1 - j) \cdot (2(i - 1) + 1 - j - 1)\)
    • \(j + 1\)转移过来,那么插入的地方为一个是情侣之间的空隙,一个是非情侣之间的空隙,方案数为\((2(i - 1) + 1 - (j + 1)) \cdot (j + 1) \cdot 2\),乘2是因为这是两类不同位置,两人可以交换位置
    • \(j + 2\)转移过来,那么插入的地方为两个情侣之间的空隙,方案数为\((j + 2) \cdot (j + 1)\)

最后的答案显然为

\[\begin{eqnarray*} \sum\limits_{i = 0}^n D^i \cdot f[n][i] \end{eqnarray*} \]

代码:

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define N 1010
const ll p = 998244353;
int n, D;
//f[n][i]表示在第2n个位置,有i对情侣相邻的方案数
ll f[N][N];
void add(ll &x, ll y) {
	x += y;
	if (x >= p) x -= p;
}

int main() {
	memset(f, 0, sizeof f);
	f[1][1] = 2;
	for (int i = 2; i <= 1000; ++i) {
		for (int j = 0; j <= i; ++j) {
			//情侣看成一个点插入
			if (j) add(f[i][j], f[i - 1][j - 1] * (2 * i - 1 - (j - 1)) % p * 2 % p);
			add(f[i][j], f[i - 1][j] * j % p * 2 % p);
			//情侣看成两个点插入
			add(f[i][j], f[i - 1][j] * (2 * i - 1 - j) % p * (2 * i - 1 - j - 1) % p);
			if (j < i - 1) add(f[i][j], f[i - 1][j + 1] * (j + 1) % p * (2 * i - 1 - (j + 1)) % p * 2 % p);
			if (j < i - 2) add(f[i][j], f[i - 1][j + 2] * (j + 2) % p * (j + 1) % p);
		}
	}
	while (scanf("%d%d", &n, &D) != EOF) {
		ll DD = 1;
		ll res = 0;
		for (int i = 0; i <= n; ++i) {
			add(res, DD * f[n][i] % p);
			DD = DD * D % p;
		}
		printf("%lld\n", res);
	}
	return 0;
}
posted @ 2019-07-13 10:27  Dup4  阅读(148)  评论(0编辑  收藏  举报