#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353, N = 5e5;
int qmod1(const int &x) { return x >= mod ? x - mod : x; }
int qmod2(const int &x) { return x + (x >> 31 & mod); }
int qpower(int a, int b) {
  int ans = 1;
  for (; b; b >>= 1, a = 1ll * a * a % mod)
    if (b & 1) ans = 1ll * ans * a % mod;
  return ans;
}
struct Z {
  int x;
  Z(int v = 0) { x = qmod2(v % mod); }
  int qmod1(const int &x) const { return x >= mod ? x - mod : x; }
  int qmod2(const int &x) const { return x + (x >> 31 & mod); }
  int qpower(int a, int b) const {
    int ans = 1;
    for (; b; b >>= 1, a = 1ll * a * a % mod)
      if (b & 1) ans = 1ll * ans * a % mod;
    return ans;
  }
  Z operator+(const Z &b) const { return (Z){qmod1(x + b.x)}; }
  Z &operator+=(const Z &b) {
    x += b.x;
    if (x >= mod) x -= mod;
    return *this;
  }
  Z operator-(const Z &b) const { return (Z){qmod2(x - b.x)}; }
  Z &operator-=(const Z &b) {
    x -= b.x;
    x += x >> 31 & mod;
    return *this;
  }
  Z operator*(const Z &b) const { return (Z){(int)(1ll * x * b.x % mod)}; }
  Z &operator*=(const Z &b) {
    x = 1ll * x * b.x % mod;
    return *this;
  }
  int inv() const {
    assert(x != 0);
    return qpower(x, mod - 2);
  }
  Z operator/(const Z &b) const { return (Z){(int)(1ll * x * b.inv() % mod)}; }
  Z &operator/=(const Z &b) {
    x = 1ll * x * b.inv() % mod;
    return *this;
  }
  Z operator-() const { return (Z){qmod2(-x)}; }
};
bool zero(const Z &a) { return !a.x; }
void print(const Z &a) { printf("%d", a.x); }
Z inv[N], fac[N], ifac[N];
void prework(int n) {
  fac[0] = 1;
  for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * Z(i);
  inv[1] = 1;
  for (int i = 2; i <= n; i++) inv[i] = Z(mod - mod / i) * inv[mod % i];
  ifac[0] = 1;
  for (int i = 1; i <= n; i++) ifac[i] = ifac[i - 1] * inv[i];
}
template <typename T>
void simplify(T &a) {
  while (a.size() && zero(a[-1])) a.pop_back();
}
template <typename T>
bool zero(const T &a) {
  int n = a.size() - 1;
  while (n >= 0 && zero(a[n])) --n;
  return n < 0;
}
int limn = 0;
void setn(const int &n) { limn = n; }
template <class T>
struct Poly {
  vector<T> a;
  Poly() { a.resize(0); }
  Poly(const T &u, const T &v) {
    a.resize(2);
    a[0] = u, a[1] = v;
  }
  Poly(const int &u, const int &v) {
    a.resize(2);
    a[0] = u, a[1] = v;
  }
  Poly(const int &x) {
    a.resize(1);
    a[0] = T(x);
  }
  Poly(const T &x) {
    a.resize(1);
    a[0] = x;
  }
  int size() const { return a.size(); }
  void resize(const int &x) { a.resize(x); }
  void clear() { vector<T>().swap(a); }
  void pop_back() { a.pop_back(); }
  T operator[](const int &x) const {
    assert(x < (int)a.size());
    if (x >= 0) return a[x];
    assert(-x <= (int)a.size());
    return a[a.size() + x];
  }
  T &operator[](const int &x) {
    assert(x < (int)a.size());
    if (x >= 0) return a[x];
    assert(-x <= (int)a.size());
    return a[a.size() + x];
  }
  Poly<T> operator*(const Poly<T> &b) const {
    Poly<T> c;
    if (!a.size() || !b.size()) return c;
    int n = a.size(), m = b.size();
    c.resize(n + m - 1);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) c[i + j] += a[i] * b[j];
    simplify(c);
    return c;
  }
  Poly<T> operator*(const T &b) const {
    Poly<T> c;
    int n = a.size();
    c.resize(n);
    for (int i = 0; i < (int)a.size(); i++) c[i] = a[i] * b;
    return c;
  }
  Poly<T> operator+(const Poly &b) const {
    Poly c;
    int n = a.size(), m = b.size();
    c.resize(max(n, m));
    for (int i = 0; i < n && i < m; i++) c[i] = a[i] + b[i];
    if (n < m)
      copy(b.a.begin() + n, b.a.end(), c.a.begin() + n);
    else
      copy(a.begin() + m, a.end(), c.a.begin() + m);
    simplify(c);
    return c;
  }
  Poly<T> operator-() const {
    Poly c;
    int n = a.size();
    c.resize(n);
    for (int i = 0; i < n; i++) c[i] = -a[i];
    return c;
  }
  Poly<T> operator-(const Poly<T> &b) const {
    Poly c;
    int n = a.size(), m = b.size();
    c.resize(max(n, m));
    for (int i = 0; i < n && i < m; i++) c[i] = a[i] - b[i];
    if (n < m)
      for (int i = n; i < m; i++) c[i] = -b[i];
    else
      copy(a.begin() + m, a.end(), c.a.begin() + m);
    simplify(c);
    return c;
  }
  Poly<T> operator/(const Poly<T> &b) const {
    assert(!zero(b));
    Poly c;
    int n = a.size(), m = b.size();
    if (n < m) return c;
    Poly<T> tmp = *this;
    c.resize(n - m + 1);
    for (int i = n - 1; i >= m - 1; i--) {
      T t = tmp[i] / b[m - 1];
      c[i - m + 1] = t;
      for (int j = 0; j < m; j++) tmp[i - j] -= b[m - 1 - j] * t;
    }
    return c;
  }
  Poly<T> operator%(const Poly<T> &b) const {
    assert(!zero(b));
    Poly<T> c;
    int n = a.size(), m = b.size();
    c = *this;
    for (int i = n - 1; i >= m - 1; i--) {
      T t = c[i] / b[m - 1];
      for (int j = 0; j < m; j++) c[i - j] -= b[m - 1 - j] * t;
    }
    simplify(c);
    return c;
  }
  Poly<T> &operator+=(const Poly<T> &b) {
    *this = *this + b;
    return *this;
  }
  Poly<T> &operator-=(const Poly<T> &b) {
    *this = *this - b;
    return *this;
  }
  Poly<T> &operator*=(const Poly<T> &b) {
    *this = *this * b;
    return *this;
  }
  Poly<T> &operator*=(const T &b) {
    *this = *this * b;
    return *this;
  }
  Poly<T> &operator/=(const Poly<T> &b) {
    *this = *this / b;
    return *this;
  }
  Poly<T> &operator%=(const Poly<T> &b) {
    *this = *this % b;
    return *this;
  }
  template <typename S>
  S operator()(const S &b) const {
    S ans;
    Poly<T> a = *this;
    int n = limn ? limn : a.size();
    a.resize(n);
    for (int i = n - 1; i >= 0; i--) {
      ans = ans * b + S(a[i]);
      if (limn) ans.resize(limn);
    }
    return ans;
  }
};
void print(const Poly<Z> &a) {
  int n = a.size();
  if (!n) {
    printf("0");
    return;
  }
  for (int i = n - 1; i >= 1; i--) print(a[i]), printf("x^%d + ", i);
  print(a[0]);
}
template <typename T>
Poly<T> monic(const Poly<T> &a) {
  Poly<T> ans = a;
  simplify(ans);
  if (zero(ans)) return ans;
  T t = ans[-1].inv();
  for (int i = 0; i < ans.size(); i++) ans[i] = a[i] * t;
  return ans;
}
template <typename T>
Poly<T> gcd(const Poly<T> &a, const Poly<T> &b) {
  if (zero(b)) return monic(a);
  return gcd(b, a % b);
}
template <typename T>
Poly<T> lcm(const Poly<T> &a, const Poly<T> &b) {
  if (zero(a) || zero(b)) return Poly<T>();
  return a * b / gcd(a, b);
}
template <typename T>
pair<Poly<T>, Poly<T> > exgcd(const Poly<T> &a, const Poly<T> &b,
                              const Poly<T> &c = Poly<T>(1)) {
  if (zero(b)) {
    assert(zero(c % a));
    return make_pair(c / a, 0);
  }
  pair<Poly<T>, Poly<T> > t = exgcd(b, a % b, c);
  return make_pair(t.second, t.first - a / b * t.second);
}
Poly<Z> Der(const Poly<Z> &a) {
  Poly<Z> ans;
  int n = a.size();
  if (n <= 1) return ans;
  ans.resize(n - 1);
  for (int i = 0; i < n - 1; i++) ans[i] = a[i + 1] * (Z(i + 1));
  return ans;
}
Poly<Z> Ln(const Poly<Z> &A) {
  Poly<Z> a = A;
  int n = limn ? limn : a.size();
  a.resize(n);
  Poly<Z> ans;
  ans.resize(n);
  ans[0] = 0;
  assert(a[0].x == 1);
  for (int i = 1; i < n; i++) {
    ans[i] = Z(i) * a[i];
    for (int j = 0; j < i; j++) ans[i] -= ans[j] * a[i - j];
  }
  for (int i = 1; i < n; i++) ans[i] *= inv[i];
  return ans;
}
Poly<Z> Exp(const Poly<Z> &A) {
  Poly<Z> a = A;
  int n = limn ? limn : a.size();
  a.resize(n);
  Poly<Z> ans;
  ans.resize(n);
  ans[0] = 1;
  assert(a[0].x == 0);
  for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) ans[i] += ans[j] * a[i - j] * Z(i - j);
    ans[i] *= inv[i];
  }
  return ans;
}
Poly<Z> Inv(const Poly<Z> &A) {
  Poly<Z> a = A;
  int n = limn ? limn : a.size();
  a.resize(n);
  Poly<Z> ans;
  ans.resize(n);
  Z iv = a[0].inv();
  ans[0] = iv;
  for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) ans[i] -= ans[j] * a[i - j];
    ans[i] *= iv;
  }
  return ans;
}
Poly<Z> Pow(const Poly<Z> &A, const int &K) {
  Poly<Z> a = A;
  int n = limn ? limn : a.size();
  a.resize(n);
  Poly<Z> tmp = a;
  simplify(tmp);
  if (zero(tmp)) return tmp;
  int pos = 0;
  for (int i = 0; i < tmp.size(); i++)
    if (!zero(tmp[i])) {
      pos = i;
      break;
    }
  copy(tmp.a.begin() + pos, tmp.a.end(), tmp.a.begin());
  tmp.resize(tmp.size() - pos);
  Z iv = tmp[0].inv();
  for (int i = 0; i < tmp.size(); i++) tmp[i] * iv;
  Poly<Z> ans = tmp;
  ans.resize(n);
  ans = Ln(ans);
  for (int i = 1; i < n; i++) ans[i] *= K;
  ans = Exp(ans);
  if (pos * K >= n) return Poly<Z>();
  ans.resize(ans.size() + pos * K);
  copy(ans.a.begin(), ans.a.end(), ans.a.begin() + pos * K);
  ans.resize(n);
  iv = iv.inv();
  iv = qpower(iv.x, K);
  for (int i = 0; i < n; i++) ans[i] *= iv;
  return ans;
}
Poly<Z> Sqrt(const Poly<Z> &a) { return Pow(a, (mod + 1) >> 1); }
Poly<Z> mul(const Poly<Z> &A, const Poly<Z> &B) {
  Poly<Z> a = A, b = B;
  int n;
  if (limn)
    n = limn, a.resize(n), b.resize(n);
  else
    n = a.size() + b.size() - 1, a.resize(n), b.resize(n);
  Poly<Z> ans;
  ans.resize(n);
  for (int i = 0; i < n; i++)
    for (int j = 0; j + i < n; j++) ans[i + j] += a[i] * b[j];
  return ans;
}
struct FRAC {
  Poly<Z> u, v;
  FRAC(const Z &x) {
    u = x;
    v = Z(1);
  }
  FRAC(const int &x) {
    u = Z(x);
    v = Z(1);
  }
  FRAC() { u = Z(0), v = Z(1); }
  FRAC(const Poly<Z> &_u) {
    u = _u;
    v = Z(1);
  }
  FRAC(const Poly<Z> &_u, const Poly<Z> &_v) {
    u = _u, v = _v;
    simplify(u), simplify(v);
    if (zero(u)) {
      v = 1;
      return;
    }
    Poly<Z> d = gcd(u, v);
    u /= d, v /= d;
    Poly<Z> c = v[-1];
    u /= c, v /= c;
  }
  FRAC operator+(const FRAC &a) const {
    return (FRAC){u * a.v + v * a.u, v * a.v};
  }
  FRAC operator-(const FRAC &a) const {
    return (FRAC){u * a.v - v * a.u, v * a.v};
  }
  FRAC operator*(const FRAC &a) const { return (FRAC){u * a.u, v * a.v}; }
  FRAC operator/(const FRAC &a) const { return (FRAC){u * a.v, v * a.u}; }
  FRAC operator-() const { return (FRAC){-u, v}; }
  FRAC operator()(const FRAC &a) const {
    FRAC fz, fm;
    for (int i = (int)u.size() - 1; i >= 0; i--) fz = fz * a + (FRAC){u[i]};
    for (int i = (int)v.size() - 1; i >= 0; i--) fm = fm * a + (FRAC){v[i]};
    return fz / fm;
  }
  FRAC inv() { return (FRAC){v, u}; }
};
bool zero(const FRAC &a) { return zero(a.u); }
FRAC &operator+=(FRAC &a, const FRAC &b) {
  a = a + b;
  return a;
}
FRAC &operator-=(FRAC &a, const FRAC &b) {
  a = a - b;
  return a;
}
FRAC &operator*=(FRAC &a, const FRAC &b) {
  a = a * b;
  return a;
}
FRAC &operator/=(FRAC &a, const FRAC &b) {
  a = a / b;
  return a;
}
FRAC Der(const FRAC &a) {
  return (FRAC){Der(a.u) * a.v - a.u * Der(a.v), a.v * a.v};
}
void print(const FRAC &a) {
  putchar('('), print(a.u), printf(") / (");
  print(a.v);
  putchar(')');
}
struct Basis {
  vector<Poly<FRAC> > a;
  vector<Poly<FRAC> > c;
  int n;
  Basis(int _n) {
    n = _n;
    a.resize(n);
    for (int i = 0; i < n; i++) a[i].resize(n);
    c.resize(n);
    for (int i = 0; i < n; i++) c[i].resize(n);
  }
  pair<bool, Poly<FRAC> > ins(Poly<FRAC> x) {
    Poly<FRAC> tc;
    tc.resize(n);
    for (int i = 0; i < n; i++) {
      if (zero(x[i])) continue;
      if (zero(a[i])) {
        a[i] = x;
        c[i] = tc;
        c[i][i] = 1;
        return make_pair(1, 0);
      }
      FRAC t = -x[i] / a[i][i];
      tc[i] = t;
      x += a[i] * t;
      x.resize(n);
    }
    for (int j = 0; j < n; j++) tc[j] = -tc[j];
    Poly<FRAC> ans;
    ans.resize(n);
    setn(n);
    for (int j = 0; j < n; j++) ans += c[j] * tc[j];
    setn(0);
    simplify(ans);
    return make_pair(0, ans);
  }
};
template <typename T>
int mindeg(const Poly<T> &a) {
  int n = a.size() - 1;
  for (int i = 0; i < n; i++)
    if (!zero(a[i])) return i;
  return -1;
}
struct ODE {
  Poly<FRAC> a;
  int size() const { return a.size(); }
  int length() const {
    Poly<Z> t = 1;
    for (int i = 0; i < (int)a.size(); i++) t = lcm(t, a[i].v);
    Poly<FRAC> tmpa = a;
    for (int i = 0; i < (int)tmpa.size(); i++) tmpa[i] *= (FRAC){t};
    int mxpos = tmpa.size() - mindeg(t), mipos = tmpa.size() - (t.size() - 1);
    for (int i = 0; i < (int)tmpa.size(); i++)
      if (!zero(tmpa[i]))
        mxpos = max(mxpos, i - mindeg(tmpa[i].u)),
        mipos = min(mipos, i - (int)(tmpa[i].u.size() - 1));
    return mxpos - mipos;
  }
  Poly<Z> geta(const Poly<Z> &a0, const int &n) const {
    int m = a0.size();
    Poly<Z> t = 1;
    for (int i = 0; i < (int)a.size(); i++) t = lcm(t, a[i].v);
    Poly<FRAC> tmpa = a;
    for (int i = 0; i < (int)tmpa.size(); i++) tmpa[i] *= (FRAC){t};
    int mxpos = tmpa.size() - mindeg(t), mipos = tmpa.size() - (t.size() - 1);
    for (int i = 0; i < (int)tmpa.size(); i++)
      if (!zero(a[i]))
        mxpos = max(mxpos, i - mindeg(tmpa[i].u)),
        mipos = min(mipos, i - (int)(tmpa[i].u.size() - 1));
    assert(m >= mxpos - mipos);
    vector<vector<Z> > pw;
    pw.resize(n + 1);
    for (int i = 0; i <= n; i++) {
      pw[i].resize(tmpa.size() + 1);
      pw[i][0] = 1;
      for (int j = 1; j < (int)pw[i].size(); j++)
        pw[i][j] = pw[i][j - 1] * (Z){i - j + 1};
    }
    Poly<Z> ans = a0;
    ans.resize(n + 1);
    for (int i = m; i <= n; i++) {
      Z u = 0, v = 0;
      for (int j = 0; j < t.size(); j++) {
        if (zero(t[j])) continue;
        int d = mxpos - (tmpa.size() - j);
        if (!d)
          u += t[j] * pw[i][tmpa.size()];
        else
          v -= pw[i - d][tmpa.size()] * t[j] * ans[i - d];
      }
      for (int j = 0; j < (int)tmpa.size(); j++)
        for (int k = 0; k < tmpa[j].u.size(); k++) {
          if (zero(tmpa[j].u[k])) continue;
          int d = mxpos - (j - k);
          if (!d)
            u -= tmpa[j].u[k] * pw[i][j];
          else
            v += ans[i - d] * pw[i - d][j] * tmpa[j].u[k];
        }
      assert(!zero(u) || zero(v));
      if (!zero(u))
        ans[i] = v / u;
      else
        ans[i] = 1;
    }
    return ans;
  }
};
bool zero(const ODE &a) { return zero(a.a); }
void print(const ODE &a) {
  if (!a.size()) {
    puts("F=0");
    return;
  }
  int n = a.size();
  printf("F(%d) =", n);
  putchar('('), print(a.a[0]);
  printf(")F");
  for (int i = 1; i < n; i++)
    printf(" + "), printf("("), print(a.a[i]), printf(")F(%d)", i);
  puts("");
}
ODE operator+(const ODE &A, const ODE &B) {
  if (zero(A)) return B;
  if (zero(B)) return A;
  Poly<FRAC> a = A.a, b = B.a;
  int n = a.size(), m = b.size();
  ODE ans;
  Poly<FRAC> tmp;
  tmp.resize(n + m);
  tmp[0] = 1, tmp[n] = 1;
  Basis bs(n + m);
  for (;;) {
    pair<bool, Poly<FRAC> > t = bs.ins(tmp);
    if (!t.first) {
      ans.a = t.second;
      break;
    }
    FRAC u = tmp[n - 1];
    tmp[n - 1] = Der(tmp[n - 1]);
    for (int i = n - 2; i >= 0; i--) tmp[i + 1] += tmp[i], tmp[i] = Der(tmp[i]);
    for (int i = 0; i < n; i++) tmp[i] += u * a[i];
    u = tmp[n + m - 1];
    tmp[n + m - 1] = Der(tmp[n + m - 1]);
    for (int i = n + m - 2; i >= n; i--)
      tmp[i + 1] += tmp[i], tmp[i] = Der(tmp[i]);
    for (int i = n; i < n + m; i++) tmp[i] += u * b[i - n];
  }
  return ans;
}
ODE operator*(const ODE &A, const ODE &B) {
  if (zero(A)) return B;
  if (zero(B)) return A;
  Poly<FRAC> a = A.a, b = B.a;
  int n = a.size(), m = b.size();
  ODE ans;
  Poly<FRAC> tmp;
  tmp.resize(n * m);
  tmp[0] = 1;
  Basis bs(n * m);
  for (int T = 0;; ++T) {
    pair<bool, Poly<FRAC> > t = bs.ins(tmp);
    if (!t.first) {
      ans.a = t.second;
      break;
    }
    Poly<FRAC> ttmp = tmp;
    tmp.clear();
    tmp.resize(n * m);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) {
        tmp[i * m + j] += Der(ttmp[i * m + j]);
        if (i != n - 1)
          tmp[(i + 1) * m + j] += ttmp[i * m + j];
        else {
          for (int k = 0; k < n; k++) tmp[k * m + j] += ttmp[i * m + j] * a[k];
        }
        if (j != m - 1)
          tmp[i * m + j + 1] += ttmp[i * m + j];
        else {
          for (int k = 0; k < m; k++) tmp[i * m + k] += ttmp[i * m + j] * b[k];
        }
      }
  }
  return ans;
}
ODE composite(const ODE &A, const FRAC &b) {
  if (zero(A)) return A;
  ODE ans;
  Poly<FRAC> tmp;
  Poly<FRAC> a = A.a;
  int n = a.size();
  FRAC db = Der(b);
  tmp.resize(n);
  tmp[0] = 1;
  Basis bs(n);
  for (;;) {
    pair<bool, Poly<FRAC> > t = bs.ins(tmp);
    if (!t.first) {
      ans.a = t.second;
      break;
    }
    FRAC u = tmp[n - 1] * db;
    tmp[n - 1] = Der(tmp[n - 1]);
    for (int i = n - 2; i >= 0; i--)
      tmp[i + 1] += tmp[i] * db, tmp[i] = Der(tmp[i]);
    if (!zero(u))
      for (int i = 0; i < n; i++) tmp[i] += a[i](b) * u;
  }
  return ans;
}
Poly<FRAC> trans_vector(const vector<Poly<FRAC> > &a, const int &n,
                        const int &m) {
  Poly<FRAC> ans;
  ans.resize(n * m);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
      ans[i * m + j] = a[i][j];
    }
  return ans;
}
Poly<FRAC> composite(const FRAC &a, const Poly<FRAC> &b) {
  Poly<FRAC> u, v;
  u.resize(a.u.size()), v.resize(a.v.size());
  for (int i = 0; i < a.u.size(); i++) u[i] = a.u[i];
  for (int i = 0; i < a.v.size(); i++) v[i] = a.v[i];
  return exgcd(v % b, b, u % b).first % b;
}
void print(const Poly<FRAC> &a) {
  int n = a.size();
  putchar('('), print(a[0]), putchar(')');
  for (int i = 1; i < n; i++) printf(" + ("), print(a[i]), printf(")u^%d", i);
  puts("");
}
ODE composite(const ODE &A, const Poly<FRAC> &B) {
  if (!A.size()) return A;
  Poly<FRAC> b = monic(B);
  assert(b.size() > 1);
  Poly<FRAC> a = A.a;
  ODE ans;
  vector<Poly<FRAC> > tmp;
  assert(b.size() > 1);
  int n = a.size(), m = b.size();
  Poly<FRAC> du;
  {
    Poly<FRAC> u = b;
    for (int i = 0; i < m; i++) u[i] = Der(u[i]);
    simplify(u);
    Poly<FRAC> v = b;
    for (int i = 0; i < m - 1; i++) v[i] = v[i + 1] * FRAC(Poly<Z>(i + 1));
    v.pop_back();
    du = exgcd(v, b, -u).first % b;
  }
  --m;
  tmp.resize(n);
  tmp[0] = Poly<FRAC>(1);
  for (int i = 0; i < n; i++) tmp[i].resize(m);
  Basis bs(n * m);
  int T = 0;
  for (;;) {
    pair<bool, Poly<FRAC> > t = bs.ins(trans_vector(tmp, n, m));
    if (!t.first) {
      ans.a = t.second;
      break;
    }
    vector<Poly<FRAC> > ttmp = tmp;
    tmp.clear();
    tmp.resize(n);
    for (int i = 0; i < n; i++) tmp[i].resize(m);
    for (int i = 0; i < n; i++)
      for (int j = 0; j < m; j++) tmp[i][j] += Der(ttmp[i][j]);
    for (int i = 0; i < n - 1; i++) {
      Poly<FRAC> t = du * ttmp[i] % b;
      tmp[i + 1] += t;
    }
    for (int i = 0; i < n; i++)
      tmp[i] += composite(a[i], b) * du * ttmp[n - 1] % b;
    for (int i = 0; i < n; i++) {
      Poly<FRAC> t = ttmp[i];
      for (int j = 0; j < t.size() - 1; j++) t[j] = FRAC(j + 1) * t[j + 1];
      t.pop_back();
      tmp[i] += t * du % b;
    }
    for (int i = 0; i < n; i++) tmp[i].resize(m);
  }
  return ans;
}
Poly<Z> calc0(const int &n, const int &len) {
  setn(len);
  Poly<Z> X(0, 1);
  Poly<Z> t;
  t.resize(3);
  t[0] = 1, t[1] = 6, t[2] = 1;
  t = Sqrt(t);
  Poly<Z> r = (Poly<Z>(1, 1) + t) * Z((mod + 1) >> 1);
  return mul(Pow(r, n), Inv(t));
}
ODE getODE(const int &n) {
  Poly<Z> X(0, 1);
  ODE ans;
  ODE t;
  t.a = Poly<FRAC>(FRAC(n, X));
  Poly<FRAC> tf;
  tf.resize(3);
  tf[0] = -X, tf[1] = Poly<Z>(-1, -1), tf[2] = 1;
  ans = ans * composite(t, tf);
  t.a = Poly<FRAC>(FRAC((mod - 1) >> 1, X));
  FRAC tx;
  tx.u.resize(3);
  tx.u[0] = 1, tx.u[1] = 6, tx.u[2] = 1;
  ans = ans * composite(t, tx);
  return ans;
}
int main() {
  int n, K;
  scanf("%d%d", &n, &K);
  int tK = K;
  K = min(K, n);
  prework(20);
  ODE h = getODE(n + 1);
  Poly<Z> ans = h.geta(calc0(n + 1, h.length()), K);
  for (int i = 1; i <= K; i++) print(ans[i]), putchar(' ');
  for (int i = K + 1; i <= tK; i++) putchar('0'), putchar(' ');
  puts("");
}
