|
|
更好的阅读体验:https://www.cnblogs.com/To-Carpe-Diem/p/19645638 更好的阅读体验(加强版):https://www.cnblogs.com/To-Carpe-Diem/p/19645952 $\newcommand{\binom}[2]{{#1 \choose #2}}$ 大意 $n$ 对情侣,恰好 $k$ 对在 $2 \times n$ 的电影院中坐一起的方案数。
思路 很好的题目,使得我的大脑旋转。 首先我们先定义函数 $f(n, k)$ 表示 $n$ 对情侣有 $k$ 对恰好坐到一块的方案数。首先我们要从 $n$ 对情侣中选择 $k$ 对,这个是 $\binom{n}{k}$ 的,再从 $n$ 排选择 $k$ 排,这个也是 $\binom{n}{k}$ 的,考虑到这 $k$ 对情侣间也有先后顺序,贡献就是 $k!$,两人可以换位,贡献是 $2 ^ k$,剩下有 $n - k$ 对情侣,我们只需要将其错排即可。 定义 $g(m)$ 表示 $m$ 对情侣错排的方案数,我们考虑这个怎么求。这个我们可以利用容斥原理,我们考虑直接计算至少 $j$ 对和睦的方案数,那么这个的贡献与上面的类似,应当是 $\binom{m}{j} ^ 2 j! 2 ^ j (2(m - j))!$,那么由容斥可知:$g(m) = \sum_{j = 0} ^ {m}(-1) ^ j \binom{m}{j} ^ 2 j! 2 ^ j (2(m - j))!$ 那么我们合并一下整个式子,就是:$f(n, k) = \binom{n}{k} ^ 2 k ! 2 ^ k g(n - k) = \binom{n}{k} ^ 2 k ! 2 ^ k \sum_{j = 0} ^ {n - k}(-1) ^ j \binom{n - k}{j} ^ 2 j! 2 ^ j (2(n - k - j))!$ 这个式子我们是可以直接求的,于是就完成了。 接下来进入正题,我们注意到刚刚的弱化版内的 $f(n, k) = \binom{n}{k} ^ 2 k ! 2 ^ k D(n - k) $,且 $D(n) = \sum_{i = 0} ^ {n} (-1) ^ i\binom{n}{i} ^ 2 i! 2 ^ i (2(n - i))!$,我们考虑对于 $D(n)$ 进行化简. $\sum_{i = 0} ^ {n}(-1) \binom{n}{i} ^ 2 i! 2 ^ i (2(n - i)) != (n!) ^ 2 \sum_{i = 0} ^ n \frac{(2(n - i))!}{(n - i)! ^ 2} \frac{(-2) ^ i}{i!}$ 这里我们就可以直接做卷积了,但是问题在于这个题目要求的复杂度太过苛刻,卷积无法通过此题,我们考虑构造生成函数。 我们设:$F(x) = (n!) ^ 2 \sum_{i = 0} ^ n \frac{(2(n - i))!}{(n - i)! ^ 2} \frac{(-2) ^ i}{i!} x^i,G[n] = \frac{(2n)!}{n!^2},P[n] = \frac{(-2) ^ i}{n !}$。那么,由离散卷积可知:$F(x) = G(x) * P(x)$ 接下来,我们只需要分别对于 $G(x)$ 和 $P(x)$ 化简即可。首先,对于 $G(x)$ 来说,我们可以利用**广义二项式定理**,那么什么是广义二项式定理呢?对于任意实数 $\alpha$,都有 $(1 + z) ^ \alpha = \sum_{i = 0} ^ {\infty} \binom{\alpha}{i} z ^ i$,那么说我们就可以化简 $G(x)$ 了:$G(x) = \sum_{i = 0} \frac{(-2x) ^ i}{i!} x ^ i = \sum_{i = 0} \binom{2i}{i}x^i = \frac{1}{\sqrt{1 - 4x}}$对于 $P(x)$ 来说,直接化简:$P(x) = \sum_{i = 0} \frac{(-2x)!}{i!} = e ^ {-2x}$ 经过化简,我们可以最终得到:$F(x) = \frac{e ^ {-2x}}{\sqrt{1 - 4x}}$对于这个生成函数,为了得到与自身相关的式子进行递推,我们选择对其求导。$F'(x) = \frac{8x * e ^ {-2x}}{(1 - 4x) ^ \frac{3}{2}} = \frac{8x}{1 - 4x} F(x)$整理一下:$F'(x) = 4xF'(x) + 8xF(x)$。提取 $[x ^ n]$ 的系数:$F'[n] = 4xF'[n - 1] + 8xF[n - 1]$。稍施小计,我们可以直接得到关于 $F[n]$ 的递推式:$(n + 1)F[n + 1] = 4nF[n] + 8F[n - 1]$ 你可能以为万事大吉了,但是问题是我们还有个 $(n!) ^ 2$ 的系数在最开始被我们提出去了,我们要把这玩意弄回来,带入 $F[n] = \frac{D(n)}{n!} ^ 2$:$(n + 1)\frac{D[n + 1]}{(n + 1)!} = 4n \frac{D[n]}{n!^2} + 8 \frac{D[n - 1]}{(n - 1)! ^ 2}$我们就可以得到关于 $D[n]$ 的递推式:$D[n + 1] = 4n(n + 1)D[n] + 8n ^ 2(n + 1)D[n - 1]$ 直接 $O(n)$ 递推即可。
代码
#include<iostream>
using namespace std;
#define int long long
const int MOD = 998244353;
const int MAXN = 2e3 + 5;
int C[MAXN][MAXN];
int fac[MAXN];
int g[MAXN], pow2[MAXN];
void init(){
C[0][0] = 1;
for(int i = 1;i < MAXN;i ++){
C[i][0] = C[i][i] = 1;
for(int j = 1;j < i;j ++){
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
}
}
fac[0] = 1;
for(int i = 1;i < MAXN;i ++){
fac[i] = (fac[i - 1] * i) % MOD;
}
pow2[0] = 1;
for(int i = 1;i < MAXN;i ++){
pow2[i] = pow2[i - 1] * 2 % MOD;
}
for(int m = 0;m <= 1000;m ++){
g[m] = 0;
for(int j = 0;j <= m;j ++){
int a = (j % 2 == 0) ? 1 : MOD - 1;
int res = C[m][j] * C[m][j] % MOD;
res = (res * fac[j]) % MOD;
res = (res * pow2[j]) % MOD;
res = (res * fac[2 * (m - j)]) % MOD;
res = (res * a) % MOD;
g[m] = (g[m] + res) % MOD;
}
}
return;
}
int f(int n, int k){
int res = (C[n][k] * C[n][k]) % MOD;
res = (res * fac[k]) % MOD;
res = (res * pow2[k]) % MOD;
res = (res * g[n - k]) % MOD;
return res;
}
int T, n, k;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
init();
cin >> T;
while(T --){
cin >> n;
for(int i = 0;i <= n;i ++){
cout << f(n, i) << '\n';
}
}
return 0;
}
2026-02-27 11:52:19
|