情侣?给我烧了!
有 (n) 对情侣来到电影院观看电影。在电影院,恰好留有 (n) 排座位,每排包含 (2) 个座位,共 (2×n) 个座位。 现在,每个人将会随机坐在某一个位置上,且恰好将这 (2 × n) 个座位坐满。 如果一对情侣坐在了同一排的座位上,那么我们称这对情侣是和睦的。 你的任务是求出当 (k = 0, 1, ... , n) 时,共有多少种不同的就坐方案满足恰好有 (k) 对情侣是和睦的。 两种就坐方案不同当且仅当存在一个人在两种方案中坐在了不同的位置。不难发现,一共会有 ((2n)!) 种不同的就坐方案。 由于结果可能较大,因此输出对 (998244353) 取模的结果。
对于 (100 \%) 的数据,满足 (1 leq T leq 2 imes 10^5, 1 leq n leq 5 imes 10^6, 0 leq k leq n)。
生成函数做法
https://www.luogu.com.cn/blog/EntropyIncreaser/solution-p4931
给出一个生成函数爆算递推式的方式:
不妨设 (D_n) 是这个问题的“错排”:每对情侣都不在一排的方案数。那么对于答案 (f(n, k)) 来说就可以用 (D_n) 进行表示,即考虑坐在一排的情侣是哪几对且他们在哪几排,即
因为 (sum_{k=0}^n f(n,k)=(2n)!),所以有恒等式
其中 (inom nk^2) 引导我们将生成函数写成
那么因为
这个 (frac{(2n)!}{n!^2}) 类似卡特兰数推导过程的中间量。尝试手动展开 (frac{1}{sqrt{1-4x}})
[[x^n]frac{1}{sqrt{1-4x}}=inom{-1/2}{n}(-4)^n=frac{prod_{i=0}^{n-1}(-1/2-i)}{n!}(-4)^n\ =frac{(2n-1)!!}{n!}2^n=frac{(2n-1)!!}{n!}frac{(2n)!!}{n!}=frac{(2n)!}{n!n!} ]
带入原式,我们得到了 (D(x)) 的生成函数方程
因此
这帮助我们得到一个式子用于计算 (D_n)(其实就是容斥)
或者也可以直接卷积,但是这都不够快速。我们考虑对 (D(x)) 进行求导。
这个微分方程可以帮助我们写出 (D(x)) 的递推形式了,即
提取系数有
组合做法
https://www.luogu.com.cn/blog/Linnewww/solution-p4931
模仿标准错排数的推导过程,我们来推导情侣错排数。
先考虑第一排放什么。
-
放一对基佬,方案数 (inom{n}{2}2=n(n-1))。
-
放一对妹子,同上。
-
放不是情侣的一男一女,方案数 (inom{n}{2}2cdot 2=2n(n-1))。
然后考虑剩下的位置,显然关键点在于第一排放的人的配偶。
-
坐在一起。那么共有 (2(n-1)D_{n-2}) 种方案。
-
不坐在一起,相当于一对情侣的限制。那么共有 (D_{n-1}) 种方案。
综上所述,(D_n=4n(n-1)(D_{n-1}+2(n-1)D_{n-2}))。
CO int N=5e6+10;
int fac[N],ifac[N],bas[N],D[N];
IN int binom(int n,int m){
return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main(){
fac[0]=1;
for(int i=1;i<N;++i) fac[i]=mul(fac[i-1],i);
ifac[N-1]=fpow(fac[N-1],mod-2);
for(int i=N-2;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
bas[0]=1;
for(int i=1;i<N;++i) bas[i]=add(bas[i-1],bas[i-1]);
D[0]=1,D[1]=0;
for(int i=2;i<N;++i){
D[i]=add(D[i-1],mul(2*(i-1),D[i-2]));
D[i]=mul(D[i],mul(4*i,i-1));
}
for(int T=read<int>();T--;){
int n=read<int>(),k=read<int>();
int ans=mul(binom(n,k),mul(binom(n,k),fac[k]));
ans=mul(ans,mul(bas[k],D[n-k]));
printf("%d
",ans);
}
return 0;
}