专栏文章

【3】题解:P4931 [MtOI2018] 情侣?给我烧了!(加强版)【组合数学】

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min4b1v4
此快照首次捕获于
2025/12/01 20:20
3 个月前
此快照最后确认于
2025/12/01 20:20
3 个月前
查看原文
我们考虑如何使用组合数学来做这道生成函数。你首先知道这是一个错排问题。考虑一个组合方案是 fi,jf_{i,j} 为有 ii 对情侣 jj 对在一起的方案数。我们显然有一个排列为 (ij)\binom{i}{j} 为选择 jj 个对在一起。然后我们考虑这些人的顺序,有 AijA_{i}^j 的方案。然后左右互换是 2j2^j,总方案数是 fi,j=(ij)×Aij×2jf_{i,j}=\binom{i}{j}\times A_i^j\times 2^j
然后其他的情况就需要考虑情侣 iji-j 对不坐在一起的情况。设 gkg_kkk 对情侣不在一起的方案数。首先是男通 / 百合就是 k(k1)k(k-1)。然后非情侣的就是男选一女不能选显然就是 2k(k1)2k(k-1)。然后他们原始的配偶就需要递归进去为 gk2g_{k-2}gk1g_{k-1}。综合这里可以计算出来 gk=4k(k1)(gk1+2(k1)gk2)g_k=4k(k-1)(g_{k-1}+2(k-1)g_{k-2})。计算是容易的。
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5e6+10;
const ll P=998244353;
ll qp(ll a,ll b){
	ll res=1;
	for(;b;b>>=1,a=(a*a)%P)
		if(b&1) res=(res*a)%P;
	return res;
}
ll fac[N],fiv[N],f[N],p2[N];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll n=5e6,k,T;
	fac[0]=1, p2[0]=1;
	for(int i=1;i<=n;i++)
		fac[i]=fac[i-1]*i%P,
		p2[i]=p2[i-1]*2%P;
	fiv[n]=qp(fac[n],P-2);
	for(int i=n;i>=1;i--)
		fiv[i-1]=fiv[i]*i%P;
	f[0]=1,f[1]=0;
	for(int i=2;i<=n;i++)	
		f[i]=(f[i-1]+f[i-2]*2*(i-1)%P)%P*4%P*i%P*(i-1)%P;
	cin>>T;
	while(T--){
		cin>>n>>k;	
		cout<<fac[n]*fiv[n-k]%P*fac[n]%P*fiv[k]%P*fiv[n-k]%P*p2[k]%P*f[n-k]%P<<"\n";
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...