CF285E题解

果然数数题比什么阴间巨大多细节哈希点分治简单多了

恰好太难了,考虑容斥,考虑钦定 \(m\) 个位置满足 \(|i-p_i|=1\)

很明显有 \(f(m)=\sum_{i=m}^{n}\binom{i}{m}g(i)\),二项式反演一下就有 \(g(m)=\sum_{i=m}^{n}\binom{i}{m}(-1)^{i-m}f(i)\)

\(dp[n][m][0/1][0/1]\) 表示前 \(n\) 个位置中共有 \(m\) 个满足 \(|i-p_i|=1\) 的且仅考虑这一部分对答案贡献的方案数,且是/否存在 \(j\) 满足 \(p_j=n-1\)\(p_j=n\)。那么有 \(f(m)=dp[n][m][0/1][0/1]\times(n-m)!\)

这个比较好转移。复杂度 \(O(n^2)\)

鹰角你什么时候送我们六星自选卷啊

提交记录

好吧代码在这里

#include<iostream>
const int M=1005,mod=1e9+7;
int n,m,F[M],inv[M],fac[M],X[2][2][M],Y[2][2][M],*f[2][2],*g[2][2];
inline int Add(const int&a,const int&b){
	return a+b>=mod?a+b-mod:a+b;
}
signed main(){
	int ans(0);std::cin>>n>>m;for(int i=0;i^2;++i)for(int j=0;j^2;++j)f[i][j]=X[i][j],g[i][j]=Y[i][j];
	f[0][0][0]=1;f[0][1][1]=1;inv[1]=fac[0]=fac[1]=1;for(int i=2;i<=n;++i)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=2;i<=n;++i)fac[i]=1ll*fac[i-1]*i%mod;
	for(int i=2;i<=n;++i){
		for(int k=1;k<=i;++k){
			g[0][0][k]=Add(Add(f[0][0][k],f[1][0][k]),f[0][0][k-1]);g[0][1][k]=Add(f[0][0][k-1],f[1][0][k-1]);
			g[1][0][k]=Add(Add(f[0][1][k],f[1][1][k]),f[0][1][k-1]);g[1][1][k]=Add(f[0][1][k-1],f[1][1][k-1]);
		}
		g[0][0][0]=1;for(int i=0;i^2;++i)for(int j=0;j^2;++j)std::swap(f[i][j],g[i][j]);
	}
	for(int i=0;i<=n;++i)F[i]=1ll*Add(f[0][0][i],f[1][0][i])*fac[n-i]%mod;
	for(int C(1),i=m;i<=n;++i,C=1ll*i*inv[i-m]%mod*C%mod)ans=(ans+1ll*C*(i-m&1?mod-F[i]:F[i]))%mod;std::cout<<ans;
}
posted @ 2022-07-27 15:24  Prean  阅读(16)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};