[ARC118E] Avoid Permutations 题解
[ARC118E] Avoid Permutations 题解
考虑容斥,当前路径经过了多少个障碍物,因为填 \(-1\) 的位置具体填什么未知,所以还需要记录目前没确定的 \(-1\) 的个数。
所以可以写出 状态表示 \(f_{i, j, k}\) 表示当前在 \((i, j)\),及之前 \(k\) 个 \(-1\) 未确定。
因为转移的时候不知道下一个位置同行同列是否有障碍物,所以实际的状态还需要记录一下当前行/列有没有 \(-1\) 障碍物。
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <iostream>
#define x first
#define y second
//#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 200 + 10, mod = 998244353;
int n, p[N], f[N][N][N][2][2], fac[N], m;
bool ok[N];
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> p[i], m += p[i] == -1;
if(p[i] != -1) ok[p[i]] = 1;
}
ok[0] = ok[n + 1] = 1;
f[0][0][0][0][0] = 1;
for(int i = 0; i <= n + 1; i ++) {
for(int j = 0; j <= n + 1; j ++) {
for(int k = 0; k <= m; k ++) {
for(int ox = 0; ox < 2; ox ++) {
for(int oy = 0; oy < 2; oy ++) {
int v = f[i][j][k][ox][oy];
if(!v) continue;
(f[i + 1][j][k][0][oy] += v) %= mod;
(f[i][j + 1][k][ox][0] += v) %= mod;
if(!oy && p[i + 1] == -1 && !ok[j]) (f[i + 1][j][k + 1][1][1] -= v) %= mod;
if(!ox && p[i] == -1 && !ok[j + 1]) (f[i][j + 1][k + 1][1][1] -= v) %= mod;
if(p[i + 1] > 0 && p[i + 1] == j) (f[i + 1][j][k][0][oy] -= v) %= mod;
if(p[i] > 0 && p[i] == j + 1) (f[i][j + 1][k][ox][0] -= v) %= mod;
// cout << i << ' ' << j << ' ' << k << ' ' << ox << ' ' << oy << ' ' << f[i][j][k][ox][oy] << '\n';
}
}
}
}
}
int ans = 0;
fac[0] = 1;
for(int i = 1; i <= m; i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
for(int k = 0; k <= m; k ++) {
for(int x = 0; x < 2; x ++) {
for(int y = 0; y < 2; y ++) {
ans = (ans + 1ll * f[n + 1][n + 1][k][x][y] * fac[m - k] % mod) % mod;
}
}
}
cout << (ans + mod) % mod << '\n';
return 0;
}

QwQ
浙公网安备 33010602011771号