AT_abc309_g 题解
AT_abc309_g [ABC309G] Ban Permutation
题目大意
求长为 且满足以下条件的排列 的个数:
- ,。
思路
第一眼看到这一题就知道不能够直接求(废话)。
看到大于等于一眼想到容斥和状压。可以考虑将问题转化一下,钦定 个位置满足条件 。
具体地说,令 表示前 个位置中有 个位置满足条件 ,目前不合法区域选择状态为 ,转移的时候讨论是否满足条件即可,还有一车细节需要注意。除了这 个位置以外其余的位置都可以随便排,所以还需要乘上 才行。
综上所述,易知答案为: 总的时间复杂度为 ,应该是可以过的吧……
记得开 long long
记得开 long long
记得开 long long
在这里祭了不知道多久……
代码
#include <iostream>
#define int long long
#define MAXN 105
#define MAXX 15
#define mod 998244353
using namespace std;
int n, x, t, ans;
int f[MAXN][MAXN][MAXX * MAXN], fac[MAXN];
signed main(){
cin >> n >> x;fac[0] = 1;
for(int i = 1 ; i <= n ; i ++)
fac[i] = fac[i - 1] * i % mod;
x--;
f[0][0][0] = 1;
for(int i = 1 ; i <= n ; i ++){
for(int j = 0 ; j < i ; j ++){
for(int s = 0 ; s < (1 << ((x << 1) + 1)) ; s ++){
if (!f[i - 1][j][s])continue;t = (s >> 1);
f[i][j][t] += f[i - 1][j][s];f[i][j][t] %= mod;
for(int k = 0 ; k <= (x << 1) ; k ++){
if ((~t) & (1 << k)){
if (i + k - x < 1 || i + k - x > n)continue;
f[i][j + 1][t | (1 << k)] += f[i - 1][j][s];
f[i][j + 1][t | (1 << k)] %= mod;
}
}
}
}
}
for(int i = 0 ; i <= n ; i ++){
for(int s = 0 ; s < (1 << (x * 2 + 1)); s ++){
t = (i & 1) ? (mod - f[n][i][s]) : f[n][i][s];
ans = (ans + t * fac[n - i] % mod) % mod;
}
}
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】