Problem: Note that the only differences between easy and hard versions are the constraints on n and the time limit. You can make hacks only if all versions are solved.

Slime is interested in sequences. He defined good positive integer sequences p of length n as follows:

  * For each k>1 that presents in p, there should be at least one pair of indices i,j, such that 1 ≤ i < j ≤ n, p_i = k - 1 and p_j = k.



For the given integer n, the set of all good sequences of length n is s_n. For the fixed integer k and the sequence p, let f_p(k) be the number of times that k appears in p. For each k from 1 to n, Slime wants to know the following value:

$$$\left(∑_{p∈ s_n} f_p(k)\right)\ mod\ 998 244 353$$$

Input

The first line contains one integer n\ (1≤ n≤ 5000).

Output

Print n integers, the i-th of them should be equal to \left(∑_{p∈ s_n} f_p(i)\right)\ mod\ 998 244 353.

Examples

Input


2


Output


3 1 


Input


3


Output


10 7 1 


Input


1


Output


1 

Note

In the first example, s=\{[1,1],[1,2]\}.

In the second example, s=\{[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,2],[1,2,3]\}.

In the third example, s=\{[1]\}.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7, M = (1 << 19), mod = 998244353, G = 3,
          iG = (mod + 1) / G, inv2 = (mod + 1) / 2;
int qpow(int x, int y = mod - 2) {
  int res = 1;
  for (; y; x = (long long)x * x % mod, y >>= 1)
    if (y & 1) res = (long long)res * x % mod;
  return res;
}
int lim, pp[M];
void po_up(int x) {
  for (lim = 1; lim <= x; lim <<= 1)
    ;
}
void po_cle(int *f) {
  for (int i = 0, iE = lim - 1; i <= iE; i++) f[i] = 0;
}
void ntt(int *f, int flag = 1) {
  for (int i = 0, iE = lim - 1; i <= iE; i++)
    pp[i] = ((pp[i >> 1] >> 1) | ((i & 1) * (lim >> 1)));
  for (int i = 0, iE = lim - 1; i <= iE; i++)
    if (pp[i] < i) swap(f[pp[i]], f[i]);
  for (int i = 2; i <= lim; i <<= 1)
    for (int j = 0, l = (i >> 1), ch = qpow(flag == 1 ? G : iG, (mod - 1) / i);
         j < lim; j += i)
      for (int k = j, now = 1; k < j + l; k++) {
        int pa = f[k], pb = (long long)f[k + l] * now % mod;
        f[k] = (pa + pb) % mod, f[k + l] = (pa + mod - pb) % mod;
        now = (long long)now * ch % mod;
      }
  if (flag ^ 1)
    for (int i = 0, ilim = qpow(lim); i < lim; i++)
      f[i] = (long long)f[i] * ilim % mod;
}
void po_mul(int *f, int *g, int *ans, int n, int m) {
  static int A[M], B[M];
  po_up(n + m - 1), copy(f, f + n, A), copy(g, g + m, B);
  fill(A + n, A + lim, 0), fill(B + m, B + lim, 0), ntt(A), ntt(B);
  for (int i = 0, iE = lim - 1; i <= iE; i++)
    A[i] = (long long)A[i] * B[i] % mod;
  ntt(A, 0), copy(A, A + n + m - 1, ans);
}
void po_inv(int *f, int *g, int len) {
  static int sav[M], now[M];
  po_up(len << 1), po_cle(now), now[0] = qpow(f[0]);
  for (int m = 1, pn; m < len; m <<= 1) {
    pn = min(m << 1, len), po_up(pn << 1), po_cle(sav), copy(f, f + pn, sav),
    ntt(sav), ntt(now);
    for (int i = 0, iE = lim - 1; i <= iE; i++)
      now[i] = (long long)now[i] *
               (mod + 2 - (long long)now[i] * sav[i] % mod) % mod;
    ntt(now, -1), fill(now + pn, now + lim, 0);
  }
  copy(now, now + len, g);
}
void po_integ(int *f, int len) {
  for (int i = len, iE = 1; i >= iE; i--)
    f[i] = (long long)f[i - 1] * qpow(i) % mod;
  f[0] = 0;
}
void po_deriv(int *f, int len) {
  for (int i = 0, iE = len - 2; i <= iE; i++)
    f[i] = (long long)f[i + 1] * (i + 1) % mod;
  f[len - 1] = 0;
}
void po_ln(int *f, int *g, int len) {
  static int sav[M], sv[M];
  po_inv(f, sv, len), copy(f, f + len, sav), po_deriv(sav, len);
  po_mul(sav, sv, sv, len, len), po_integ(sv, len), copy(sv, sv + len, g);
}
void po_exp(int *f, int *g, int len) {
  static int sav[M], now[M];
  po_up(len << 1), po_cle(now), now[0] = 1;
  for (int m = 1, pn; m < len; m <<= 1) {
    pn = min(m << 1, len), po_up(pn << 1), po_cle(sav), po_ln(now, sav, pn);
    for (int i = 0, iE = pn - 1; i <= iE; i++)
      sav[i] = (mod + f[i] - sav[i]) % mod;
    (sav[0] += 1) %= mod, po_mul(now, sav, now, pn, pn),
        fill(now + pn, now + lim, 0);
  }
  copy(now, now + len, g);
}
void po_sqrt(int *f, int *g, int len) {
  static int sav[M], now[M];
  po_up(len << 1), po_cle(now), now[0] = 1;
  for (int m = 1, pn; m < len; m <<= 1) {
    pn = min(m << 1, len), po_up(pn << 1), po_cle(sav), po_inv(now, sav, pn),
    po_mul(f, sav, sav, pn, pn);
    for (int i = 0; i < pn; i++)
      now[i] = (long long)(sav[i] + now[i]) % mod * inv2 % mod;
  }
  copy(now, now + len, g);
}
void po_pow(int *f, int k, int len) {
  static int g[M];
  po_ln(f, g, len);
  for (int i = 0, iE = len - 1; i <= iE; i++) g[i] = (long long)g[i] * k % mod;
  po_exp(g, g, len), copy(g, g + len, f);
}
struct poly {
  int *f, len;
  void init(int x) {
    len = x, f = new int[x];
    fill(f, f + x, 0);
  }
  poly(int n = 0) { init(n); }
  int v(int x) { return x < 0 || x > len ? 0 : f[x]; }
  int &operator[](int x) { return f[x]; }
  friend poly operator*(poly aa, poly bb) {
    poly res(aa.len + bb.len - 1);
    po_mul(aa.f, bb.f, res.f, aa.len, bb.len);
    return res;
  }
  friend poly operator+(poly aa, poly bb) {
    int mx = max(aa.len, bb.len);
    poly res(mx);
    for (int i = 0, iE = mx - 1; i <= iE; i++)
      res.f[i] = (aa.v(i) + bb.v(i)) % mod;
    return res;
  }
  friend poly operator-(poly aa, poly bb) {
    int mx = max(aa.len, bb.len);
    poly res(mx);
    for (int i = 0, iE = mx - 1; i <= iE; i++)
      res.f[i] = (aa.v(i) + mod - bb.v(i)) % mod;
    return res;
  }
  friend poly operator*(poly aa, int bb) {
    poly res(aa.len);
    for (int i = 0, iE = aa.len - 1; i <= iE; i++)
      res.f[i] = (long long)aa.f[i] * bb % mod;
    return res;
  }
  poly &operator+=(poly aa) { return (*this) = (*this) + aa; }
  poly &operator-=(poly aa) { return (*this) = (*this) - aa; }
  poly &operator*=(poly aa) { return (*this) = (*this) * aa; }
  poly &operator*=(int aa) { return (*this) = (*this) * aa; }
  poly &operator=(poly bb) {
    len = bb.len, init(len), copy(bb.f, bb.f + len, f);
    return (*this);
  }
  poly inv() {
    poly res(len);
    po_inv(f, res.f, len);
    return res;
  }
  poly ln() {
    poly res(len);
    po_ln(f, res.f, len);
    return res;
  }
  poly exp() {
    poly res(len);
    po_exp(f, res.f, len);
    return res;
  }
  poly pow(int x) {
    poly res = *this;
    po_pow(res.f, x, len);
    return res;
  }
  poly sqrt() {
    poly res(len);
    po_sqrt(f, res.f, len);
    return res;
  }
  poly integ() {
    poly res = *this;
    po_integ(res.f, len);
    return res;
  }
  poly deriv() {
    poly res = *this;
    po_deriv(res.f, len);
    return res;
  }
};
int n, inv[N], ifac[N], fac[N], p[N];
int C(int x, int y) {
  if (x < y) return 0;
  return (long long)fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
void init(int x) {
  fac[0] = inv[1] = ifac[0] = 1;
  for (int i = 2, iE = x; i <= iE; i++)
    inv[i] = (long long)inv[mod % i] * (mod - mod / i) % mod;
  for (int i = 1, iE = x; i <= iE; i++)
    fac[i] = (long long)fac[i - 1] * i % mod,
    ifac[i] = (long long)ifac[i - 1] * inv[i] % mod;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0), cout.tie(0);
  cin >> n, init(n * 2 + 3);
  poly Q(n + 3), ans(n + 1), t(n + 1);
  for (int i = 2, iE = n + 4; i <= iE; i++) (Q[i - 2] += mod - ifac[i]) %= mod;
  for (int i = 1, iE = n + 3; i <= iE; i++) (Q[i - 1] += ifac[i]) %= mod;
  Q = Q.inv();
  for (int i = 0, iE = n * 2 + 2; i <= iE; i++)
    for (int j = 0, jE = min(i, n + 2); j <= jE; j++)
      if (i - j <= n)
        (ans[i - j] += (long long)Q.v(n + 2 - j) * C(i, j) % mod) %= mod;
  for (int i = 0, iE = n; i <= iE; i++) {
    int now = 1;
    for (int j = 0, jE = n + 2; j <= jE; j++)
      (ans[i] += mod - (long long)Q[n + 2 - j] * now % mod) %= mod,
          now = (long long)now * (i + 1) % mod * inv[j + 1] % mod;
  }
  for (int i = 0, iE = n; i <= iE; i++) {
    if (i % 2 == 0)
      t[i] = C(n + 2, i);
    else
      t[i] = mod - C(n + 2, i);
  }
  ans = ans * t;
  for (int i = 1, iE = n; i <= iE; i++)
    cout << (long long)ans[i] * fac[n] % mod << " ";
  return 0;
}