题解:AT_arc118_e [ARC118E] Avoid Permutations
Claire0918 · · 题解
我们先说明一个定理
我们记
记
现在的式子是容易 DP 的。设
我们首先有直接向下一个位置走,不选择下一个位置作为障碍的转移。
考虑选择下一个位置为障碍的转移。首先,
注意并非任意情况下都可以选择下一个位置作为状态。我们有转移
计算答案时考虑枚举
时间复杂度
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a));
using namespace std;
const int maxn = 200 + 10, mod = 998244353;
int n, res = 0;
int a[maxn], fac[maxn], f[maxn][maxn][maxn][2][2];
bitset<maxn> vis;
template<typename Tp_x, typename Tp_y>
inline void mod_add(Tp_x &x, Tp_y y){
x += y, x >= mod ? x -= mod : x;
}
int main(){
scanf("%d", &n);
int cnt = 0;
fac[0] = 1;
for (int i = 1; i <= n; i++){
fac[i] = (long long)fac[i - 1] * i % mod;
scanf("%d", &a[i]);
if (~a[i]){
cnt++, vis.set(a[i]);
}
}
f[0][0][cnt][0][0] = 1;
for (int i = 0; i <= n + 1; i++){
for (int j = 0; j <= n + 1; j++){
for (int k = cnt; k <= n; k++){
for (int p = 0; p < 2; p++){
for (int q = 0; q < 2; q++){
if (i <= n){
mod_add(f[i + 1][j][k][0][q], f[i][j][k][p][q]);
if (!q && i + 1 >= 1 && i + 1 <= n && j >= 1 && j <= n && (a[i + 1] == j || !~a[i + 1] && !vis[j])){
mod_add(f[i + 1][j][k + (a[i + 1] != j)][1][1], mod - f[i][j][k][p][q]);
}
}
if (j <= n){
mod_add(f[i][j + 1][k][p][0], f[i][j][k][p][q]);
if (!p && i >= 1 && i <= n && j + 1 >= 1 && j + 1 <= n && (a[i] == j + 1 || !~a[i] && !vis[j + 1])){
mod_add(f[i][j + 1][k + (a[i] != j + 1)][1][1], mod - f[i][j][k][p][q]);
}
}
}
}
}
}
}
for (int i = cnt; i <= n; i++){
mod_add(res, (long long)fac[n - i] * f[n + 1][n + 1][i][0][0] % mod);
}
printf("%d", res);
return 0;
}