Solution S o l u t i o n
先
dfs
dfs
出四个量
c1,c2,cyc,blk
c
1
,
c
2
,
c
y
c
,
b
l
k
表示缩边以后
x→ 0
x
→
0
,
0→x
0
→
x
,自环和
0→0
0
→
0
的边的数量。
fi
f
i
表示用
c1
c
1
可以搞出至少
i
i
个环的方案数。直接枚举放几个进去,剩下的和的搞在一起。
然后容斥一下得到恰好
i
i
个环的方案数。
同理。
0→0
0
→
0
放到
i
i
个环就是。
把这三个方案数卷起来。
因为
0→0
0
→
0
的是本质不同的。最后把答案乘上
blk!
b
l
k
!
。
复杂度是
O(n2)
O
(
n
2
)
,可以做更大的数据。
#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> pairs;
const int N = 555;
const int MOD = 998244353;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
int s[N][N], C[N][N], A[N][N];
int n, cyc, blk, c1, c2;
int vis[N], nxt[N], deg[N];
int f[N], h[N], g[N], ans[N];
int a[N], b[N];
queue<pairs> Q;
int sum(int x, int y) {
return (x + y >= MOD) ? x + y - MOD : x + y;
}
int sub(int x, int y) {
return (x < y) ? x - y + MOD : x - y;
}
void pre(int n) {
s[0][0] = C[0][0] = A[0][0] = 1;
for (int i = 1; i <= n; i++) {
C[i][0] = A[i][0] = 1; s[i][0] = 0;
for (int j = 1; j <= i; j++) {
A[i][j] = sum((ll)j * A[i - 1][j - 1] % MOD, A[i - 1][j]);
C[i][j] = sum(C[i - 1][j - 1], C[i - 1][j]);
s[i][j] = sum(s[i - 1][j - 1], (ll)(i - 1) * s[i - 1][j] % MOD);
}
}
}
inline void dfs(int u, int cur, int head) {
vis[u] = 1;
if (nxt[u]) {
if (!vis[nxt[u]]) dfs(nxt[u], cur ^ 1, head);
else ++cyc;
} else {
if (head == cur && cur == 1) ++blk;
if (head == 1 && cur == 0) ++c1;
if (head == 0 && cur == 1) ++c2;
}
}
void calc(int n, int *f) {
for (int i = 0; i <= n; i++) f[i] = 0;
for (int i = n; i >= 0; i--) {
for (int j = 0; j <= n; j++)
f[i] = sum(f[i], (ll)C[n][j] * s[j][i] % MOD * A[n - j + blk][n - j] % MOD);
for (int j = i + 1; j <= n; j++)
f[i] = sub(f[i], (ll)f[j] * C[j][i] % MOD);
}
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
read(n); pre(n);
for (int i = 1; i <= n; i++) read(a[i]);
for (int i = 1; i <= n; i++) read(b[i]);
for (int i = 1; i <= n; i++) {
if (a[i]) {
nxt[a[i] + n] = i; ++deg[i];
}
if (b[i]) {
nxt[i] = b[i] + n; ++deg[b[i] + n];
}
}
for (int i = 1; i <= n + n; i++)
if (!vis[i] && !deg[i])
dfs(i, i > n, i > n);
for (int i = 1; i <= n + n; i++)
if (!vis[i])
dfs(i, i > n, i > n);
calc(c1, f); calc(c2, g);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= i; j++)
h[i] = sum(h[i], (ll)f[j] * g[i - j] % MOD);
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= i; j++)
ans[i] = sum(ans[i], (ll)h[j] * s[blk][i - j] % MOD);
ans[i] = (ll)ans[i] * A[blk][blk] % MOD;
}
for (int i = 0; i < n; i++)
if (n - i - cyc < 0) printf("0\n");
else printf("%d ", ans[n - i - cyc]);
putchar('\n');
return 0;
}