Problem p02980 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define fi first
#define se second
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

template <uint32_t mod> struct ModInt {
  uint32_t a;
  ModInt &s(uint32_t vv) {
    a = vv < mod ? vv : vv - mod;
    return *this;
  }

  ModInt(int64_t x = 0) { s(x % mod + mod); }

  ModInt &operator+=(const ModInt &x) { return s(a + x.a); }
  ModInt &operator-=(const ModInt &x) { return s(a + mod - x.a); }
  ModInt &operator*=(const ModInt &x) {
    a = uint64_t(a) * x.a % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &x) {
    *this *= x.inv();
    return *this;
  }

  ModInt operator+(const ModInt &x) const { return ModInt(*this) += x; }
  ModInt operator-(const ModInt &x) const { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt &x) const { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt &x) const { return ModInt(*this) /= x; }
  bool operator==(const ModInt &x) const { return a == x.a; }
  bool operator!=(const ModInt &x) const { return a != x.a; }

  ModInt operator-() const { return ModInt() - *this; }
  ModInt pow(int64_t n) const {
    ModInt res(1), x(*this);
    while (n) {
      if (n & 1)
        res *= x;
      x *= x;
      n >>= 1;
    }
    return res;
  }

  ModInt inv() const { return pow(mod - 2); }
};

using mint = ModInt<998244353>;
template <uint32_t mod> istream &operator>>(istream &in, ModInt<mod> &a) {
  return (in >> a.a);
}
template <uint32_t mod>
ostream &operator<<(ostream &out, const ModInt<mod> &a) {
  return (out << a.a);
}
using mint = ModInt<998244353>;

template <class Mint, int32_t N> struct ModIntTable {
  vector<Mint> facts, finvs, invs;
  ModIntTable() : facts(N), finvs(N), invs(N) {
    const uint32_t mod = Mint(-1).a + 1;
    invs[1] = 1;
    for (int i = 2; i < N; i++)
      invs[i] = invs[mod % i] * (mod - mod / i);

    facts[0] = 1;
    finvs[0] = 1;
    for (int i = 1; i < N; i++) {
      facts[i] = facts[i - 1] * i;
      finvs[i] = finvs[i - 1] * invs[i];
    }
  }
  inline Mint fact(int n) { return facts[n]; }
  inline Mint finv(int n) { return finvs[n]; }
  inline Mint inv(int n) { return invs[n]; }
  inline Mint binom(int n, int k) { return facts[n] * finvs[k] * finvs[n - k]; }
};
ModIntTable<mint, 1 << 19> mtable;

template <class Mint, int32_t root> struct NumberTheoreticTransform {
  static void ntt(vector<Mint> &f) {
    int n = f.size();
    int s = __lg(n);

    for (int i = 0, j = 1; j < n - 1; j++) {
      for (int k = n >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(f[i], f[j]);
    }

    for (int m = 1; m <= s; m++) {
      Mint wr = Mint(root).pow(Mint(-1).a >> m);
      for (int i = 0; i < n; i += 1 << m) {
        Mint w = 1;
        for (int j = 0; j < 1 << m - 1; j++) {
          Mint f0 = f[i + j], f1 = w * f[i + j + (1 << m - 1)];
          f[i + j] = f0 + f1;
          f[i + j + (1 << m - 1)] = f0 - f1;
          w *= wr;
        }
      }
    }
  }

  static void intt(vector<Mint> &f) {
    reverse(f.begin() + 1, f.end());
    ntt(f);
    Mint in = Mint(f.size()).inv();
    for (int i = 0; i < f.size(); i++)
      f[i] *= in;
  }

  static vector<Mint> convolute(const vector<Mint> &A, const vector<Mint> &B) {
    if (A.size() == 0 || B.size() == 0)
      return {};
    int n = 1 << __lg(A.size() + B.size() - 2) + 1;

    vector<Mint> a = A, b = B;
    a.resize(n);
    b.resize(n);
    ntt(a);
    ntt(b);
    for (int i = 0; i < n; i++)
      a[i] *= b[i];
    intt(a);
    a.resize(A.size() + B.size() - 1);
    return a;
  }
};
using NTT = NumberTheoreticTransform<mint, 3>;

const uint32_t mod = 998244353;
const mint prim_root = 3;

static const int LG = 19;
mint roots[1 << (LG + 1)], iroots[1 << (LG + 1)];
struct PrepareRoots {
  PrepareRoots() {
    rep(w, LG + 1) {
      const int s = (1 << w) - 1;
      const mint g = prim_root.pow((mod - 1) / (1 << w)), ig = g.inv();
      mint p = 1, ip = 1;
      rep(i, 1 << w) {
        roots[s + i] = p;
        p *= g;
        iroots[s + i] = ip;
        ip *= ig;
      }
    }
  }
} PrepareRootsDummy;

void broken_fmt(vector<mint> &f) {
  const int n = f.size();
  for (int b = n / 2; b >= 1; b /= 2) {
    for (int i = 0; i < n; i += b * 2) {
      rep(j, b) {
        mint tmp = f[i + j] - f[i + j + b];
        f[i + j] += f[i + j + b];
        f[i + j + b] = tmp * roots[b * 2 - 1 + j];
      }
    }
  }
}

void broken_ifmt(vector<mint> &f) {
  const int n = f.size();
  for (int b = 1; b <= n / 2; b *= 2) {
    for (int i = 0; i < n; i += b * 2) {
      rep(j, b) {
        f[i + j + b] *= iroots[b * 2 - 1 + j];
        mint tmp = f[i + j] - f[i + j + b];
        f[i + j] += f[i + j + b];
        f[i + j + b] = tmp;
      }
    }
  }
  mint in = mint(n).inv();
  rep(i, n) f[i] *= in;
}

void inplace_fmt(vector<mint> &f, const bool i = false) {
  if (!i)
    broken_fmt(f);
  else
    broken_ifmt(f);
}

vector<mint> multiply(vector<mint> x, vector<mint> y, bool same = false) {
  int n = x.size() + y.size() - 1;
  int s = 1;
  while (s < n)
    s *= 2;
  x.resize(s);
  inplace_fmt(x, false);
  if (!same) {
    y.resize(s);
    inplace_fmt(y, false);
  } else
    y = x;
  rep(i, s) x[i] *= y[i];
  inplace_fmt(x, true);
  x.resize(n);
  return x;
}

template <class Mint> struct NTTFriendlyPoly {
  void ntt(vector<Mint> &f) {
    int n = f.size();
    int s = __lg(n);

    for (int i = 0, j = 1; j < n - 1; j++) {
      for (int k = n >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(f[i], f[j]);
    }

    for (int m = 1; m <= s; m++) {
      Mint wr = Mint(3).pow(Mint(-1).a >> m);
      for (int i = 0; i < n; i += 1 << m) {
        Mint w = 1;
        for (int j = 0; j < 1 << m - 1; j++) {
          Mint f0 = f[i + j], f1 = w * f[i + j + (1 << m - 1)];
          f[i + j] = f0 + f1;
          f[i + j + (1 << m - 1)] = f0 - f1;
          w *= wr;
        }
      }
    }
  }

  void intt(vector<Mint> &f) {
    reverse(f.begin() + 1, f.end());
    ntt(f);
    Mint in = Mint(f.size()).inv();
    for (int i = 0; i < f.size(); i++)
      f[i] *= in;
  }

  vector<Mint> convolute(const vector<Mint> &A, const vector<Mint> &B) {
    if (A.size() == 0 || B.size() == 0)
      return {};
    int n = 1 << __lg(A.size() + B.size() - 2) + 1;

    vector<Mint> a = A, b = B;
    a.resize(n);
    b.resize(n);
    ntt(a);
    ntt(b);
    for (int i = 0; i < n; i++)
      a[i] *= b[i];
    intt(a);
    a.resize(A.size() + B.size() - 1);
    return a;
  }

  vector<Mint> v;
  template <class... Args> NTTFriendlyPoly(Args... args) : v(args...) {}

  NTTFriendlyPoly(const initializer_list<Mint> &in) : v(in.begin(), in.end()) {}

  int size() const { return v.size(); }

  inline Mint coef(const int i) const {
    return (i < v.size()) ? v[i] : Mint(0);
  }

  NTTFriendlyPoly operator+(const NTTFriendlyPoly &x) {
    int n = max(size(), x.size());
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = coef(i) + x.coef(i);
    return res;
  }
  NTTFriendlyPoly operator-(const NTTFriendlyPoly &x) {
    int n = max(size(), x.size());
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = coef(i) - x.coef(i);
    return res;
  }
  NTTFriendlyPoly operator*(const NTTFriendlyPoly &x) {
    return multiply(v, x.v);
  }
  NTTFriendlyPoly operator*(const Mint &x) {
    int n = size();
    vector<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = v[i] * x;
    return res;
  }
  NTTFriendlyPoly operator/(const Mint &x) { return (*this) * x.inv(); }

  NTTFriendlyPoly &operator+=(const NTTFriendlyPoly &x) {
    return *this = (*this) + x;
  }
  NTTFriendlyPoly &operator-=(const NTTFriendlyPoly &x) {
    return *this = (*this) - x;
  }
  NTTFriendlyPoly &operator*=(const NTTFriendlyPoly &x) {
    return *this = (*this) * x;
  }
  NTTFriendlyPoly &operator*=(const Mint &x) { return *this = (*this) * x; }
  NTTFriendlyPoly &operator/=(const Mint &x) { return *this = (*this) / x; }
  NTTFriendlyPoly operator-() { return NTTFriendlyPoly() - *this; }

  NTTFriendlyPoly pre(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n && i < size(); i++)
      res[i] = v[i];
    return res;
  }
  NTTFriendlyPoly rev() {
    vector<Mint> res = v;
    while (res.size() && res.back() == 0)
      res.pop_back();
    reverse(res.begin(), res.end());
    return res;
  }
  NTTFriendlyPoly diff(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 1; i < size() && i <= n; i++)
      res[i - 1] = v[i] * i;
    return res;
  }
  NTTFriendlyPoly inte(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < size() && i + 1 < n; i++)
      res[i + 1] = v[i] * mtable.inv(i + 1);
    return res;
  }

  NTTFriendlyPoly inv(int n) {
    vector<mint> res{coef(0).inv()};

    for (int d = 1; d < n; d <<= 1) {
      vector<Mint> f(2 * d), g(2 * d);
      for (int j = 0; j < 2 * d; j++)
        f[j] = coef(j);
      for (int j = 0; j < d; j++)
        g[j] = res[j];

      inplace_fmt(f);
      inplace_fmt(g);
      for (int j = 0; j < 2 * d; j++)
        f[j] *= g[j];
      inplace_fmt(f, true);
      for (int j = 0; j < d; j++) {
        f[j] = 0;
        f[j + d] = -f[j + d];
      }
      inplace_fmt(f);
      for (int j = 0; j < 2 * d; j++)
        f[j] *= g[j];
      inplace_fmt(f, true);
      for (int j = 0; j < d; j++)
        f[j] = res[j];
      res = f;
    }
    return NTTFriendlyPoly(res).pre(n);
  }

  NTTFriendlyPoly inv2(int n) {
    NTTFriendlyPoly res{coef(0).inv()};
    for (int i = 1; i < n; i *= 2) {
      res = (res * Mint(2) - res * res * pre(2 * i)).pre(2 * i);
    }
    return res.pre(n);
  }

  NTTFriendlyPoly exp(int n) {
    NTTFriendlyPoly f0{1}, g0{1};
    vector<Mint> F0{1};
    for (int d = 1; d < n; d <<= 1) {
      vector<Mint> G0 = g0.v;
      inplace_fmt(G0);
      vector<Mint> Delta(d);
      for (int j = 0; j < d; j++)
        Delta[j] = F0[j] * G0[j];
      inplace_fmt(Delta, true);
      Delta[0] -= 1;
      NTTFriendlyPoly delta(2 * d);
      for (int j = 0; j < d; j++)
        delta[d + j] = Delta[j];

      NTTFriendlyPoly epsilon(2 * d);

      vector<Mint> DF0 = f0.diff(d - 1).v;
      DF0.push_back(0);
      inplace_fmt(DF0);
      for (int j = 0; j < d; j++)
        DF0[j] *= G0[j];
      inplace_fmt(DF0, true);
      for (int j = 0; j < d - 1; j++) {
        epsilon[j] += coef(j + 1) * (j + 1);
        epsilon[j + d] += DF0[j] - coef(j + 1) * (j + 1);
      }
      epsilon[d - 1] += DF0[d - 1];

      Delta = delta.v;
      inplace_fmt(Delta);
      vector<Mint> DH0 = diff(d - 1).v;
      DH0.resize(2 * d);
      inplace_fmt(DH0);
      for (int j = 0; j < 2 * d; j++)
        Delta[j] *= DH0[j];
      inplace_fmt(Delta, true);
      for (int j = 0; j < d; j++)
        epsilon[j + d] -= Delta[j + d];

      epsilon = epsilon.inte(2 * d) - pre(2 * d);

      vector<Mint> Epsilon = epsilon.v;
      inplace_fmt(Epsilon);
      rep(j, d) DH0[j] = f0[j], DH0[j + d] = 0;
      inplace_fmt(DH0);
      rep(j, 2 * d) Epsilon[j] *= DH0[j];
      inplace_fmt(Epsilon, true);
      f0.v.resize(2 * d);
      rep(j, d) f0[j + d] -= Epsilon[j + d];
      // f0=(f0-epsilon*f0).pre(2*d);

      G0.resize(2 * d);
      rep(j, d) G0[j] = g0[j];
      inplace_fmt(G0);
      F0 = f0.v;
      inplace_fmt(F0);
      vector<Mint> T(2 * d);
      rep(j, 2 * d) T[j] = F0[j] * G0[j];
      inplace_fmt(T, true);
      rep(j, d) {
        T[j] = 0;
        T[j + d] = -T[j + d];
      }
      inplace_fmt(T);
      rep(j, 2 * d) T[j] *= G0[j];
      inplace_fmt(T, true);
      rep(j, d) T[j] = g0[j];
      g0 = T;
    }
    return f0.pre(n);
  }

  NTTFriendlyPoly exp2(int n) {
    NTTFriendlyPoly f{1};
    for (int i = 1; i < n; i *= 2) {
      f = (f * (pre(2 * i) - f.log(2 * i)) + f).pre(2 * i);
    }
    return f.pre(n);
  }

  NTTFriendlyPoly exp3(int n) {
    NTTFriendlyPoly f{1}, g{1};
    for (int d = 1; d < n; d <<= 1) {
      g = g * Mint(2) - (g * g * f).pre(d);

      NTTFriendlyPoly q = diff(d - 1);
      q = q + g * (f.diff(d - 1) - f * q).pre(2 * d - 1);
      f = f + (f * (pre(2 * d) - q.inte(2 * d))).pre(2 * d);
    }
    return f.pre(n);
  }

  NTTFriendlyPoly log(int n) { return (diff(n - 1) * inv(n - 1)).inte(n); }

  NTTFriendlyPoly pow(int n, mint k) {
    auto res = log(n);
    res *= k;
    return res.exp(n);
  }
  Mint &operator[](const int i) { return v[i]; }
};
using poly = NTTFriendlyPoly<mint>;

template <class Mint>
ostream &operator<<(ostream &ost, NTTFriendlyPoly<Mint> a) {
  for (int i = 0; i < a.size(); i++) {
    if (i)
      cout << " ";
    cout << a.v[i];
  }
  return ost;
}

signed main() {
  int N, M;
  cin >> N >> M;

  poly p(N + 1);

  auto in = mint(N + 1).inv();
  for (int i = 0; i <= N; i++) {
    p[i] = mtable.finv(i) * in * (N + 1 - i);
  }

  p = p.pow(N + 1, M);

  mint ans = 0;
  for (int i = 0; i <= N; i++) {
    ans += p[i] * mtable.finv(N - i);
  }
  ans *= mtable.fact(N);
  ans *= mint(N + 1).pow(M);
  cout << ans << endl;
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define fi first
#define se second
typedef vector<int> vint;
typedef pair<int, int> pint;
typedef vector<pint> vpint;

template <typename A, typename B> inline void chmin(A &a, B b) {
  if (a > b)
    a = b;
}
template <typename A, typename B> inline void chmax(A &a, B b) {
  if (a < b)
    a = b;
}

template <uint32_t mod> struct ModInt {
  uint32_t a;
  ModInt &s(uint32_t vv) {
    a = vv < mod ? vv : vv - mod;
    return *this;
  }

  ModInt(int64_t x = 0) { s(x % mod + mod); }

  ModInt &operator+=(const ModInt &x) { return s(a + x.a); }
  ModInt &operator-=(const ModInt &x) { return s(a + mod - x.a); }
  ModInt &operator*=(const ModInt &x) {
    a = uint64_t(a) * x.a % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &x) {
    *this *= x.inv();
    return *this;
  }

  ModInt operator+(const ModInt &x) const { return ModInt(*this) += x; }
  ModInt operator-(const ModInt &x) const { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt &x) const { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt &x) const { return ModInt(*this) /= x; }
  bool operator==(const ModInt &x) const { return a == x.a; }
  bool operator!=(const ModInt &x) const { return a != x.a; }

  ModInt operator-() const { return ModInt() - *this; }
  ModInt pow(int64_t n) const {
    ModInt res(1), x(*this);
    while (n) {
      if (n & 1)
        res *= x;
      x *= x;
      n >>= 1;
    }
    return res;
  }

  ModInt inv() const { return pow(mod - 2); }
};

using mint = ModInt<998244353>;
template <uint32_t mod> istream &operator>>(istream &in, ModInt<mod> &a) {
  return (in >> a.a);
}
template <uint32_t mod>
ostream &operator<<(ostream &out, const ModInt<mod> &a) {
  return (out << a.a);
}
using mint = ModInt<998244353>;

template <class Mint, int32_t N> struct ModIntTable {
  vector<Mint> facts, finvs, invs;
  ModIntTable() : facts(N), finvs(N), invs(N) {
    const uint32_t mod = Mint(-1).a + 1;
    invs[1] = 1;
    for (int i = 2; i < N; i++)
      invs[i] = invs[mod % i] * (mod - mod / i);

    facts[0] = 1;
    finvs[0] = 1;
    for (int i = 1; i < N; i++) {
      facts[i] = facts[i - 1] * i;
      finvs[i] = finvs[i - 1] * invs[i];
    }
  }
  inline Mint fact(int n) { return facts[n]; }
  inline Mint finv(int n) { return finvs[n]; }
  inline Mint inv(int n) { return invs[n]; }
  inline Mint binom(int n, int k) { return facts[n] * finvs[k] * finvs[n - k]; }
};
ModIntTable<mint, 1 << 19> mtable;

template <class Mint, int32_t root> struct NumberTheoreticTransform {
  static void ntt(vector<Mint> &f) {
    int n = f.size();
    int s = __lg(n);

    for (int i = 0, j = 1; j < n - 1; j++) {
      for (int k = n >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(f[i], f[j]);
    }

    for (int m = 1; m <= s; m++) {
      Mint wr = Mint(root).pow(Mint(-1).a >> m);
      for (int i = 0; i < n; i += 1 << m) {
        Mint w = 1;
        for (int j = 0; j < 1 << m - 1; j++) {
          Mint f0 = f[i + j], f1 = w * f[i + j + (1 << m - 1)];
          f[i + j] = f0 + f1;
          f[i + j + (1 << m - 1)] = f0 - f1;
          w *= wr;
        }
      }
    }
  }

  static void intt(vector<Mint> &f) {
    reverse(f.begin() + 1, f.end());
    ntt(f);
    Mint in = Mint(f.size()).inv();
    for (int i = 0; i < f.size(); i++)
      f[i] *= in;
  }

  static vector<Mint> convolute(const vector<Mint> &A, const vector<Mint> &B) {
    if (A.size() == 0 || B.size() == 0)
      return {};
    int n = 1 << __lg(A.size() + B.size() - 2) + 1;

    vector<Mint> a = A, b = B;
    a.resize(n);
    b.resize(n);
    ntt(a);
    ntt(b);
    for (int i = 0; i < n; i++)
      a[i] *= b[i];
    intt(a);
    a.resize(A.size() + B.size() - 1);
    return a;
  }
};
using NTT = NumberTheoreticTransform<mint, 3>;

const uint32_t mod = 998244353;
const mint prim_root = 3;

static const int LG = 21;
mint roots[1 << (LG + 1)], iroots[1 << (LG + 1)];
struct PrepareRoots {
  PrepareRoots() {
    rep(w, LG + 1) {
      const int s = (1 << w) - 1;
      const mint g = prim_root.pow((mod - 1) / (1 << w)), ig = g.inv();
      mint p = 1, ip = 1;
      rep(i, 1 << w) {
        roots[s + i] = p;
        p *= g;
        iroots[s + i] = ip;
        ip *= ig;
      }
    }
  }
} PrepareRootsDummy;

void broken_fmt(vector<mint> &f) {
  const int n = f.size();
  for (int b = n / 2; b >= 1; b /= 2) {
    for (int i = 0; i < n; i += b * 2) {
      rep(j, b) {
        mint tmp = f[i + j] - f[i + j + b];
        f[i + j] += f[i + j + b];
        f[i + j + b] = tmp * roots[b * 2 - 1 + j];
      }
    }
  }
}

void broken_ifmt(vector<mint> &f) {
  const int n = f.size();
  for (int b = 1; b <= n / 2; b *= 2) {
    for (int i = 0; i < n; i += b * 2) {
      rep(j, b) {
        f[i + j + b] *= iroots[b * 2 - 1 + j];
        mint tmp = f[i + j] - f[i + j + b];
        f[i + j] += f[i + j + b];
        f[i + j + b] = tmp;
      }
    }
  }
  mint in = mint(n).inv();
  rep(i, n) f[i] *= in;
}

void inplace_fmt(vector<mint> &f, const bool i = false) {
  if (!i)
    broken_fmt(f);
  else
    broken_ifmt(f);
}

vector<mint> multiply(vector<mint> x, vector<mint> y, bool same = false) {
  int n = x.size() + y.size() - 1;
  int s = 1;
  while (s < n)
    s *= 2;
  x.resize(s);
  inplace_fmt(x, false);
  if (!same) {
    y.resize(s);
    inplace_fmt(y, false);
  } else
    y = x;
  rep(i, s) x[i] *= y[i];
  inplace_fmt(x, true);
  x.resize(n);
  return x;
}

template <class Mint> struct NTTFriendlyPoly {
  void ntt(vector<Mint> &f) {
    int n = f.size();
    int s = __lg(n);

    for (int i = 0, j = 1; j < n - 1; j++) {
      for (int k = n >> 1; k > (i ^= k); k >>= 1)
        ;
      if (i > j)
        swap(f[i], f[j]);
    }

    for (int m = 1; m <= s; m++) {
      Mint wr = Mint(3).pow(Mint(-1).a >> m);
      for (int i = 0; i < n; i += 1 << m) {
        Mint w = 1;
        for (int j = 0; j < 1 << m - 1; j++) {
          Mint f0 = f[i + j], f1 = w * f[i + j + (1 << m - 1)];
          f[i + j] = f0 + f1;
          f[i + j + (1 << m - 1)] = f0 - f1;
          w *= wr;
        }
      }
    }
  }

  void intt(vector<Mint> &f) {
    reverse(f.begin() + 1, f.end());
    ntt(f);
    Mint in = Mint(f.size()).inv();
    for (int i = 0; i < f.size(); i++)
      f[i] *= in;
  }

  vector<Mint> convolute(const vector<Mint> &A, const vector<Mint> &B) {
    if (A.size() == 0 || B.size() == 0)
      return {};
    int n = 1 << __lg(A.size() + B.size() - 2) + 1;

    vector<Mint> a = A, b = B;
    a.resize(n);
    b.resize(n);
    ntt(a);
    ntt(b);
    for (int i = 0; i < n; i++)
      a[i] *= b[i];
    intt(a);
    a.resize(A.size() + B.size() - 1);
    return a;
  }

  vector<Mint> v;
  template <class... Args> NTTFriendlyPoly(Args... args) : v(args...) {}

  NTTFriendlyPoly(const initializer_list<Mint> &in) : v(in.begin(), in.end()) {}

  int size() const { return v.size(); }

  inline Mint coef(const int i) const {
    return (i < v.size()) ? v[i] : Mint(0);
  }

  NTTFriendlyPoly operator+(const NTTFriendlyPoly &x) {
    int n = max(size(), x.size());
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = coef(i) + x.coef(i);
    return res;
  }
  NTTFriendlyPoly operator-(const NTTFriendlyPoly &x) {
    int n = max(size(), x.size());
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = coef(i) - x.coef(i);
    return res;
  }
  NTTFriendlyPoly operator*(const NTTFriendlyPoly &x) {
    return multiply(v, x.v);
  }
  NTTFriendlyPoly operator*(const Mint &x) {
    int n = size();
    vector<Mint> res(n);
    for (int i = 0; i < n; i++)
      res[i] = v[i] * x;
    return res;
  }
  NTTFriendlyPoly operator/(const Mint &x) { return (*this) * x.inv(); }

  NTTFriendlyPoly &operator+=(const NTTFriendlyPoly &x) {
    return *this = (*this) + x;
  }
  NTTFriendlyPoly &operator-=(const NTTFriendlyPoly &x) {
    return *this = (*this) - x;
  }
  NTTFriendlyPoly &operator*=(const NTTFriendlyPoly &x) {
    return *this = (*this) * x;
  }
  NTTFriendlyPoly &operator*=(const Mint &x) { return *this = (*this) * x; }
  NTTFriendlyPoly &operator/=(const Mint &x) { return *this = (*this) / x; }
  NTTFriendlyPoly operator-() { return NTTFriendlyPoly() - *this; }

  NTTFriendlyPoly pre(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < n && i < size(); i++)
      res[i] = v[i];
    return res;
  }
  NTTFriendlyPoly rev() {
    vector<Mint> res = v;
    while (res.size() && res.back() == 0)
      res.pop_back();
    reverse(res.begin(), res.end());
    return res;
  }
  NTTFriendlyPoly diff(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 1; i < size() && i <= n; i++)
      res[i - 1] = v[i] * i;
    return res;
  }
  NTTFriendlyPoly inte(int n) {
    NTTFriendlyPoly<Mint> res(n);
    for (int i = 0; i < size() && i + 1 < n; i++)
      res[i + 1] = v[i] * mtable.inv(i + 1);
    return res;
  }

  NTTFriendlyPoly inv(int n) {
    vector<mint> res{coef(0).inv()};

    for (int d = 1; d < n; d <<= 1) {
      vector<Mint> f(2 * d), g(2 * d);
      for (int j = 0; j < 2 * d; j++)
        f[j] = coef(j);
      for (int j = 0; j < d; j++)
        g[j] = res[j];

      inplace_fmt(f);
      inplace_fmt(g);
      for (int j = 0; j < 2 * d; j++)
        f[j] *= g[j];
      inplace_fmt(f, true);
      for (int j = 0; j < d; j++) {
        f[j] = 0;
        f[j + d] = -f[j + d];
      }
      inplace_fmt(f);
      for (int j = 0; j < 2 * d; j++)
        f[j] *= g[j];
      inplace_fmt(f, true);
      for (int j = 0; j < d; j++)
        f[j] = res[j];
      res = f;
    }
    return NTTFriendlyPoly(res).pre(n);
  }

  NTTFriendlyPoly inv2(int n) {
    NTTFriendlyPoly res{coef(0).inv()};
    for (int i = 1; i < n; i *= 2) {
      res = (res * Mint(2) - res * res * pre(2 * i)).pre(2 * i);
    }
    return res.pre(n);
  }

  NTTFriendlyPoly exp(int n) {
    NTTFriendlyPoly f0{1}, g0{1};
    vector<Mint> F0{1};
    for (int d = 1; d < n; d <<= 1) {
      vector<Mint> G0 = g0.v;
      inplace_fmt(G0);
      vector<Mint> Delta(d);
      for (int j = 0; j < d; j++)
        Delta[j] = F0[j] * G0[j];
      inplace_fmt(Delta, true);
      Delta[0] -= 1;
      NTTFriendlyPoly delta(2 * d);
      for (int j = 0; j < d; j++)
        delta[d + j] = Delta[j];

      NTTFriendlyPoly epsilon(2 * d);

      vector<Mint> DF0 = f0.diff(d - 1).v;
      DF0.push_back(0);
      inplace_fmt(DF0);
      for (int j = 0; j < d; j++)
        DF0[j] *= G0[j];
      inplace_fmt(DF0, true);
      for (int j = 0; j < d - 1; j++) {
        epsilon[j] += coef(j + 1) * (j + 1);
        epsilon[j + d] += DF0[j] - coef(j + 1) * (j + 1);
      }
      epsilon[d - 1] += DF0[d - 1];

      Delta = delta.v;
      inplace_fmt(Delta);
      vector<Mint> DH0 = diff(d - 1).v;
      DH0.resize(2 * d);
      inplace_fmt(DH0);
      for (int j = 0; j < 2 * d; j++)
        Delta[j] *= DH0[j];
      inplace_fmt(Delta, true);
      for (int j = 0; j < d; j++)
        epsilon[j + d] -= Delta[j + d];

      epsilon = epsilon.inte(2 * d) - pre(2 * d);

      vector<Mint> Epsilon = epsilon.v;
      inplace_fmt(Epsilon);
      rep(j, d) DH0[j] = f0[j], DH0[j + d] = 0;
      inplace_fmt(DH0);
      rep(j, 2 * d) Epsilon[j] *= DH0[j];
      inplace_fmt(Epsilon, true);
      f0.v.resize(2 * d);
      rep(j, d) f0[j + d] -= Epsilon[j + d];
      // f0=(f0-epsilon*f0).pre(2*d);

      G0.resize(2 * d);
      rep(j, d) G0[j] = g0[j];
      inplace_fmt(G0);
      F0 = f0.v;
      inplace_fmt(F0);
      vector<Mint> T(2 * d);
      rep(j, 2 * d) T[j] = F0[j] * G0[j];
      inplace_fmt(T, true);
      rep(j, d) {
        T[j] = 0;
        T[j + d] = -T[j + d];
      }
      inplace_fmt(T);
      rep(j, 2 * d) T[j] *= G0[j];
      inplace_fmt(T, true);
      rep(j, d) T[j] = g0[j];
      g0 = T;
    }
    return f0.pre(n);
  }

  NTTFriendlyPoly exp2(int n) {
    NTTFriendlyPoly f{1};
    for (int i = 1; i < n; i *= 2) {
      f = (f * (pre(2 * i) - f.log(2 * i)) + f).pre(2 * i);
    }
    return f.pre(n);
  }

  NTTFriendlyPoly exp3(int n) {
    NTTFriendlyPoly f{1}, g{1};
    for (int d = 1; d < n; d <<= 1) {
      g = g * Mint(2) - (g * g * f).pre(d);

      NTTFriendlyPoly q = diff(d - 1);
      q = q + g * (f.diff(d - 1) - f * q).pre(2 * d - 1);
      f = f + (f * (pre(2 * d) - q.inte(2 * d))).pre(2 * d);
    }
    return f.pre(n);
  }

  NTTFriendlyPoly log(int n) { return (diff(n - 1) * inv(n - 1)).inte(n); }

  NTTFriendlyPoly pow(int n, mint k) {
    auto res = log(n);
    res *= k;
    return res.exp(n);
  }
  Mint &operator[](const int i) { return v[i]; }
};
using poly = NTTFriendlyPoly<mint>;

template <class Mint>
ostream &operator<<(ostream &ost, NTTFriendlyPoly<Mint> a) {
  for (int i = 0; i < a.size(); i++) {
    if (i)
      cout << " ";
    cout << a.v[i];
  }
  return ost;
}

signed main() {
  int N, M;
  cin >> N >> M;

  poly p(N + 1);

  auto in = mint(N + 1).inv();
  for (int i = 0; i <= N; i++) {
    p[i] = mtable.finv(i) * in * (N + 1 - i);
  }

  p = p.pow(N + 1, M);

  mint ans = 0;
  for (int i = 0; i <= N; i++) {
    ans += p[i] * mtable.finv(N - i);
  }
  ans *= mtable.fact(N);
  ans *= mint(N + 1).pow(M);
  cout << ans << endl;
  return 0;
}