【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;
}