#include <bits/stdc++.h>
using namespace std;
inline int fast_pow(int x, int k) {
  int ans = 1;
  while (k) {
    if (k & 1) ans = 1ll * ans * x % 998244353;
    x = 1ll * x * x % 998244353;
    k >>= 1;
  }
  return ans;
}
inline int inv(int x) { return fast_pow(x, 998244353 - 2); }
inline int addm(int a, int b) {
  return a + b >= 998244353 ? a + b - 998244353 : a + b;
}
inline int decm(int a, int b) { return a < b ? a - b + 998244353 : a - b; }
int S[2000 + 5][2000 + 5], fact[2000 + 5], invfact[2000 + 5];
void ini(int n) {
  fact[0] = 1;
  for (int i = 1; i <= n; i++) fact[i] = 1ll * fact[i - 1] * i % 998244353;
  invfact[n] = inv(fact[n]);
  for (int i = n - 1; i >= 0; i--)
    invfact[i] = 1ll * invfact[i + 1] * (i + 1) % 998244353;
  for (int i = 0; i <= n; i++) {
    S[i][0] = (i == 0);
    for (int j = 1; j <= i; j++)
      S[i][j] = addm(S[i - 1][j - 1], 1ll * (i - 1) * S[i - 1][j] % 998244353);
  }
}
int binom(int n, int m) {
  return n < m ? 1
               : 1ll * fact[n] * invfact[n - m] % 998244353 * invfact[m] %
                     998244353;
}
inline int dwn(int n, int m) {
  return m == 0 ? 1 : 1ll * fact[n] * invfact[n - m] % 998244353;
}
struct poly : vector<int> {
  friend poly operator+(poly p, const poly q) {
    p.resize(max(p.size(), q.size()));
    for (int i = 0; i < (int)q.size(); i++) p[i] = addm(p[i], q[i]);
    return p;
  }
  friend poly operator*(const poly p, const poly q) {
    poly ans;
    ans.resize((int)p.size() + (int)q.size() - 1);
    for (int i = 0; i < (int)p.size(); i++) {
      for (int j = 0; j < (int)q.size(); j++)
        ans[i + j] = addm(ans[i + j], 1ll * p[i] * q[j] % 998244353);
    }
    return ans;
  }
};
poly f, g, h;
void print(const poly v) {
  for (int i = 0; i < (int)v.size(); i++) printf("%d ", v[i]);
  printf("\n");
}
struct DSU {
  int fa[2000 + 5];
  int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
  void merge(int x, int y) { fa[find(x)] = find(y); }
  void ini(int n) {
    for (int i = 1; i <= n; i++) fa[i] = i;
  }
} Se;
int n;
int p[2000 + 5], q[2000 + 5], posp[2000 + 5], posq[2000 + 5];
bool isfix[2000 + 5];
int cntfix;
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
  for (int i = 1; i <= n; i++) scanf("%d", &q[i]);
  ini(n);
  Se.ini(n);
  for (int i = 1; i <= n; i++) {
    if (p[i] && q[i]) {
      if (Se.find(p[i]) == Se.find(q[i])) cntfix++;
      Se.merge(p[i], q[i]);
      isfix[i] = 1;
    }
  }
  for (int i = 1; i <= n; i++) {
    if (isfix[i]) continue;
    p[i] = Se.find(p[i]);
    q[i] = Se.find(q[i]);
    posp[p[i]] = i;
    posq[q[i]] = i;
  }
  int A = 0, B = 0, C = 0;
  for (int i = 1; i <= n; i++) {
    if (posp[i] && posq[i]) {
      C++;
      isfix[posp[i]] = isfix[posq[i]] = 1;
    }
  }
  for (int i = 1; i <= n; i++) {
    if (isfix[i]) continue;
    if (!p[i] && q[i]) A++;
    if (p[i] && !q[i]) B++;
    if (!p[i] && !q[i]) C++;
  }
  f.resize(A + 1);
  for (int i = 0; i <= A; i++) {
    for (int j = i; j <= A; j++)
      f[i] = addm(f[i], 1ll * S[j][i] * binom(A, j) % 998244353 *
                            dwn(A + C - j - 1, A - j) % 998244353);
  }
  g.resize(B + 1);
  for (int i = 0; i <= B; i++) {
    for (int j = i; j <= B; j++)
      g[i] = addm(g[i], 1ll * S[j][i] * binom(B, j) % 998244353 *
                            dwn(B + C - j - 1, B - j) % 998244353);
  }
  h.resize(C + 1);
  for (int i = 0; i <= C; i++) h[i] = 1ll * S[C][i] * fact[C] % 998244353;
  poly ans = f * g * h;
  for (int i = 0; i < n; i++) {
    if (n - i - cntfix >= 0 && n - i - cntfix < (int)ans.size())
      printf("%d ", ans[n - i - cntfix]);
    else
      printf("0 ");
  }
}
