[abc309 G] Ban Permutation

G - Ban Permutation

首先看到绝对值,很烦,考虑取掉绝对值得到piiXpii+X

然后我们就自然而然有了一个暴力的想法,设dp[i][s]表示前i个数选了的数的状态为S,然后空间复杂度是O(N2N)的,时间复杂度也是O(N2N)

这也太暴力了8,考虑优化

发现s这一维无论如何也优化不了,考虑减小它的状态数,我们先将dp[i][s]重新定义前i个的1iXi+xN的选取状态,然后这样2N就减小为了2N2X+1

然后我们又发现X5,非常的小!所以我们考虑将dp[i][s]再次重新定义为前i个的iX+1i+X1的选取状态,发现这样,我们似乎就只能转移得到不合法的状态,但是这样我们的时空复杂度都是O(N22X1)的,可以过

所以我们考虑容斥,ans=i=0n(ni)!×val(i)i表示我们钦定了i个不合法的数

然后考虑val(i)怎么整,显然我们只需要给dp[i][s]再加上一维变成dp[i][j][s]表示前i个,有j个不合法的,目前iX+1i+X1的选取状态

那么val(i)就等于s=022X1dp[n][i][s]

然后就可以完结撒花了 *★,°*:.☆( ̄▽ ̄)/$:*.°★* 。

#include<bits/stdc++.h>
using namespace std;
const int N=105,MOD=998244353;
int n,x,dp[N][N][1<<9],lim,ans,jc[N],val[N];
void add(int &x,int y){ x+=y; if(x>=MOD) x-=MOD; if(x<0) x+=MOD; }
int ad(int x,int y){ x+=y; if(x>=MOD) x-=MOD; return x; }
void Init(){
	lim=(1<<((x<<1)-1))-1;
	jc[0]=1;
	for(int i=1;i<=n;++i) jc[i]=1ll*jc[i-1]*i%MOD;
}
int main(){
	scanf("%d%d",&n,&x),Init();
	dp[0][0][0]=1;
	for(int i=0;i<n;++i)
		for(int j=0;j<=i;++j)
			for(int s=0;s<=lim;++s){
				int now=s>>1;
				add(dp[i+1][j][now],dp[i][j][s]);
				int up=min((i+1)+x-1,n)-((i+1)-x+1),down=max(1,(i+1)-x+1)-((i+1)-x+1);
				for(int k=down;k<=up;++k) if(!(now>>k&1)) add(dp[i+1][j+1][now|(1<<k)],dp[i][j][s]);
			}
	for(int i=0;i<=n;++i) for(int s=0;s<=lim;++s) add(val[i],dp[n][i][s]);
	for(int i=0;i<=n;++i) add(ans,((i&1)?-1ll:1ll)*jc[n-i]%MOD*val[i]%MOD);
	printf("%d",ans);

	return 0;
}
posted @   LuoyuSitfitw  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示