Skip to content

formal_power_series_composition.hpp

SECTIONMath INCLUDEnoya/formal_power_series_composition.hpp

Compose two formal power series modulo x^n over 998244353. After shifting away g(0), transposition turns composition into simultaneous coefficient extraction from powers of g. A bivariate Bostan-Mori recursion halves the x degree at every level; reversing that recursion applies the transposed two-dimensional convolutions and reconstructs all coefficients.

Verified by composition_of_formal_power_series, composition_of_formal_power_series_large, compositional_inverse_of_formal_power_series, compositional_inverse_of_formal_power_series_large.

\[ \displaystyle h(x)=f(g(x)) \]

Implementation

View on GitHub

#ifndef NOYA_FORMAL_POWER_SERIES_COMPOSITION_HPP
#define NOYA_FORMAL_POWER_SERIES_COMPOSITION_HPP 1

/// @complexity Time: O(n log^2 n). Space: O(n log n).

#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>

namespace noya {

namespace formal_power_series_composition_internal {

using namespace std;

using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;

using pi = pair<ll, ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))

#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
inline int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
inline int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
inline int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
inline int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}

template <typename mint>
mint inv(int n) {
  static const int mod = mint::get_mod();
  static vector<mint> dat = {0, 1};
  assert(0 <= n);
  if (n >= mod) n %= mod;
  while (len(dat) <= n) {
    int k = len(dat);
    int q = (mod + k - 1) / k;
    dat.eb(dat[k * q - mod] * mint::raw(q));
  }
  return dat[n];
}

template <typename mint>
mint fact(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n && n < mod);
  static vector<mint> dat = {1, 1};
  while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * mint::raw(len(dat)));
  return dat[n];
}

template <typename mint>
mint fact_inv(int n) {
  static vector<mint> dat = {1, 1};
  if (n < 0) return mint(0);
  while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * inv<mint>(len(dat)));
  return dat[n];
}

template <int mod>
struct modint {
  static constexpr u32 umod = u32(mod);
  static_assert(umod < u32(1) << 31);
  u32 val;

  static modint raw(u32 v) {
    modint x;
    x.val = v;
    return x;
  }
  constexpr modint() : val(0) {}
  constexpr modint(u32 x) : val(x % umod) {}
  constexpr modint(u64 x) : val(x % umod) {}
  constexpr modint(int x) : val((x %= mod) < 0 ? x + mod : x){};
  constexpr modint(ll x) : val((x %= mod) < 0 ? x + mod : x){};
  bool operator<(const modint& other) const { return val < other.val; }
  modint& operator+=(const modint& p) {
    if ((val += p.val) >= umod) val -= umod;
    return *this;
  }
  modint& operator-=(const modint& p) {
    if ((val += umod - p.val) >= umod) val -= umod;
    return *this;
  }
  modint& operator*=(const modint& p) {
    val = u64(val) * p.val % umod;
    return *this;
  }
  modint& operator/=(const modint& p) {
    *this *= p.inverse();
    return *this;
  }
  modint operator-() const { return modint::raw(val ? mod - val : u32(0)); }
  modint operator+(const modint& p) const { return modint(*this) += p; }
  modint operator-(const modint& p) const { return modint(*this) -= p; }
  modint operator*(const modint& p) const { return modint(*this) *= p; }
  modint operator/(const modint& p) const { return modint(*this) /= p; }
  bool operator==(const modint& p) const { return val == p.val; }
  bool operator!=(const modint& p) const { return val != p.val; }
  modint inverse() const {
    int a = val, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b), swap(u -= t * v, v);
    }
    return modint(u);
  }
  modint pow(ll n) const {
    assert(n >= 0);
    modint ret(1), mul(val);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
  static constexpr int get_mod() { return mod; }
  // (n, r), r は 1 の 2^n 乗根
  static constexpr pair<int, int> ntt_info() {
    if (mod == 998244353) return {23, 31};
    return {-1, -1};
  }
  static constexpr bool can_ntt() { return ntt_info().fi != -1; }
};

using modint998 = modint<998244353>;

template <typename mint>
vc<mint> differentiate(const vc<mint>& f) {
  if (len(f) <= 1) return {};
  vc<mint> g(len(f) - 1);
  FOR(i, len(g)) g[i] = f[i + 1] * mint(i + 1);
  return g;
}

template <class T>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
  int n = int(a.size()), m = int(b.size());
  if (n > m) return convolution_naive<T>(b, a);
  if (n == 0) return {};
  vc<T> ans(n + m - 1);
  if (n <= 16 && (T::get_mod() < (1 << 30))) {
    for (int k = 0; k < n + m - 1; ++k) {
      int s = max(0, k - m + 1);
      int t = min(n, k + 1);
      u64 sm = 0;
      for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
      ans[k] = sm;
    }
  } else {
    FOR(i, n) FOR(j, m) ans[i + j] += a[i] * b[j];
  }
  return ans;
}

// 任意の環でできる
template <typename T>
vc<T> convolution_karatsuba(const vc<T>& f, const vc<T>& g) {
  const int thresh = 30;
  if (min(len(f), len(g)) <= thresh) return convolution_naive(f, g);
  int n = max(len(f), len(g));
  int m = ceil(n, 2);
  vc<T> f1, f2, g1, g2;
  if (len(f) < m) f1 = f;
  if (len(f) >= m) f1 = {f.begin(), f.begin() + m};
  if (len(f) >= m) f2 = {f.begin() + m, f.end()};
  if (len(g) < m) g1 = g;
  if (len(g) >= m) g1 = {g.begin(), g.begin() + m};
  if (len(g) >= m) g2 = {g.begin() + m, g.end()};
  vc<T> a = convolution_karatsuba(f1, g1);
  vc<T> b = convolution_karatsuba(f2, g2);
  FOR(i, len(f2)) f1[i] += f2[i];
  FOR(i, len(g2)) g1[i] += g2[i];
  vc<T> c = convolution_karatsuba(f1, g1);
  vc<T> F(len(f) + len(g) - 1);
  assert(2 * m + len(b) <= len(F));
  FOR(i, len(a)) F[i] += a[i], c[i] -= a[i];
  FOR(i, len(b)) F[2 * m + i] += b[i], c[i] -= b[i];
  if (c.back() == T(0)) c.pop_back();
  FOR(i, len(c)) if (c[i] != T(0)) F[m + i] += c[i];
  return F;
}

template <class mint>
void ntt(vector<mint>& a, bool inverse) {
  assert(mint::can_ntt());
  const int rank2 = mint::ntt_info().fi;
  const int mod = mint::get_mod();
  static array<mint, 30> root, iroot;
  static array<mint, 30> rate2, irate2;
  static array<mint, 30> rate3, irate3;

  assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));

  static bool prepared = 0;
  if (!prepared) {
    prepared = 1;
    root[rank2] = mint::ntt_info().se;
    iroot[rank2] = mint(1) / root[rank2];
    FOR_R(i, rank2) {
      root[i] = root[i + 1] * root[i + 1];
      iroot[i] = iroot[i + 1] * iroot[i + 1];
    }
    mint prod = 1, iprod = 1;
    for (int i = 0; i <= rank2 - 2; i++) {
      rate2[i] = root[i + 2] * prod;
      irate2[i] = iroot[i + 2] * iprod;
      prod *= iroot[i + 2];
      iprod *= root[i + 2];
    }
    prod = 1, iprod = 1;
    for (int i = 0; i <= rank2 - 3; i++) {
      rate3[i] = root[i + 3] * prod;
      irate3[i] = iroot[i + 3] * iprod;
      prod *= iroot[i + 3];
      iprod *= root[i + 3];
    }
  }

  int n = int(a.size());
  int h = topbit(n);
  assert(n == 1 << h);
  if (!inverse) {
    int len = 0;
    while (len < h) {
      if (h - len == 1) {
        int p = 1 << (h - len - 1);
        mint rot = 1;
        FOR(s, 1 << len) {
          int offset = s << (h - len);
          FOR(i, p) {
            auto l = a[i + offset];
            auto r = a[i + offset + p] * rot;
            a[i + offset] = l + r;
            a[i + offset + p] = l - r;
          }
          rot *= rate2[topbit(~s & -~s)];
        }
        len++;
      } else {
        int p = 1 << (h - len - 2);
        mint rot = 1, imag = root[2];
        for (int s = 0; s < (1 << len); s++) {
          mint rot2 = rot * rot;
          mint rot3 = rot2 * rot;
          int offset = s << (h - len);
          for (int i = 0; i < p; i++) {
            u64 mod2 = u64(mod) * mod;
            u64 a0 = a[i + offset].val;
            u64 a1 = u64(a[i + offset + p].val) * rot.val;
            u64 a2 = u64(a[i + offset + 2 * p].val) * rot2.val;
            u64 a3 = u64(a[i + offset + 3 * p].val) * rot3.val;
            u64 a1na3imag = (a1 + mod2 - a3) % mod * imag.val;
            u64 na2 = mod2 - a2;
            a[i + offset] = a0 + a2 + a1 + a3;
            a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
            a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
            a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
          }
          rot *= rate3[topbit(~s & -~s)];
        }
        len += 2;
      }
    }
  } else {
    mint coef = mint(1) / mint(len(a));
    FOR(i, len(a)) a[i] *= coef;
    int len = h;
    while (len) {
      if (len == 1) {
        int p = 1 << (h - len);
        mint irot = 1;
        FOR(s, 1 << (len - 1)) {
          int offset = s << (h - len + 1);
          FOR(i, p) {
            u64 l = a[i + offset].val;
            u64 r = a[i + offset + p].val;
            a[i + offset] = l + r;
            a[i + offset + p] = (mod + l - r) * irot.val;
          }
          irot *= irate2[topbit(~s & -~s)];
        }
        len--;
      } else {
        int p = 1 << (h - len);
        mint irot = 1, iimag = iroot[2];
        FOR(s, (1 << (len - 2))) {
          mint irot2 = irot * irot;
          mint irot3 = irot2 * irot;
          int offset = s << (h - len + 2);
          for (int i = 0; i < p; i++) {
            u64 a0 = a[i + offset + 0 * p].val;
            u64 a1 = a[i + offset + 1 * p].val;
            u64 a2 = a[i + offset + 2 * p].val;
            u64 a3 = a[i + offset + 3 * p].val;
            u64 x = (mod + a2 - a3) * iimag.val % mod;
            a[i + offset] = a0 + a1 + a2 + a3;
            a[i + offset + 1 * p] = (a0 + mod - a1 + x) * irot.val;
            a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * irot2.val;
            a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * irot3.val;
          }
          irot *= irate3[topbit(~s & -~s)];
        }
        len -= 2;
      }
    }
  }
}

template <class mint>
vector<mint> convolution_ntt(vector<mint> a, vector<mint> b) {
  if (a.empty() || b.empty()) return {};
  int n = int(a.size()), m = int(b.size());
  int sz = 1;
  while (sz < n + m - 1) sz *= 2;

  // sz = 2^k のときの高速化。分割統治的なやつで損しまくるので。
  if ((n + m - 3) <= sz / 2) {
    auto a_last = a.back(), b_last = b.back();
    a.pop_back(), b.pop_back();
    auto c = convolution(a, b);
    c.resize(n + m - 1);
    c[n + m - 2] = a_last * b_last;
    FOR(i, len(a)) c[i + len(b)] += a[i] * b_last;
    FOR(i, len(b)) c[i + len(a)] += b[i] * a_last;
    return c;
  }

  a.resize(sz), b.resize(sz);
  bool same = a == b;
  ntt(a, 0);
  if (same) {
    b = a;
  } else {
    ntt(b, 0);
  }
  FOR(i, sz) a[i] *= b[i];
  ntt(a, 1);
  a.resize(n + m - 1);
  return a;
}

template <typename mint>
vc<mint> convolution(const vc<mint>& a, const vc<mint>& b) {
  int n = len(a), m = len(b);
  if (!n || !m) return {};
  if (min(n, m) <= 50) return convolution_karatsuba<mint>(a, b);
  return convolution_ntt(a, b);
}

template <typename T>
vc<vc<T>> convolution2d(vc<vc<T>>& f, vc<vc<T>>& g) {
  auto shape = [&](vc<vc<T>>& f) -> pi {
    ll H = len(f);
    ll W = (H == 0 ? 0 : len(f[0]));
    return {H, W};
  };
  auto [H1, W1] = shape(f);
  auto [H2, W2] = shape(g);
  ll H = H1 + H2 - 1;
  ll W = W1 + W2 - 1;

  vc<T> ff(H1 * W);
  vc<T> gg(H2 * W);
  FOR(x, H1) FOR(y, W1) ff[W * x + y] = f[x][y];
  FOR(x, H2) FOR(y, W2) gg[W * x + y] = g[x][y];
  auto hh = convolution(ff, gg);
  vc<vc<T>> h(H, vc<T>(W));
  FOR(x, H) FOR(y, W) h[x][y] = hh[W * x + y];
  return h;
}

// a^0, ..., a^N
template <typename mint>
vc<mint> powertable_1(mint a, ll N) {
  // table of a^i
  vc<mint> f(N + 1, 1);
  FOR(i, N) f[i + 1] = a * f[i];
  return f;
}

// f(x) -> f(x+c)
template <typename mint>
vc<mint> poly_taylor_shift(vc<mint> f, mint c) {
  ll N = len(f);
  FOR(i, N) f[i] *= fact<mint>(i);
  auto b = powertable_1<mint>(c, N);
  FOR(i, N) b[i] *= fact_inv<mint>(i);
  reverse(all(f));
  f = convolution(f, b);
  f.resize(N);
  reverse(all(f));
  FOR(i, N) f[i] *= fact_inv<mint>(i);
  return f;
}

template <typename mint>
int count_terms(const vc<mint>& f) {
  int t = 0;
  FOR(i, len(f)) if (f[i] != mint(0))++ t;
  return t;
}

template <typename mint>
vc<mint> fps_inv_sparse(const vc<mint>& f) {
  int N = len(f);
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> g(N);
  mint g0 = mint(1) / f[0];
  g[0] = g0;
  FOR(n, 1, N) {
    mint rhs = 0;
    for (auto&& [k, fk]: dat) {
      if (k > n) break;
      rhs -= fk * g[n - k];
    }
    g[n] = rhs * g0;
  }
  return g;
}

template <typename mint>
vc<mint> fps_inv_dense_ntt(const vc<mint>& F) {
  vc<mint> G = {mint(1) / F[0]};
  ll N = len(F), n = 1;
  G.reserve(N);
  while (n < N) {
    vc<mint> f(2 * n), g(2 * n);
    FOR(i, min(N, 2 * n)) f[i] = F[i];
    FOR(i, n) g[i] = G[i];
    ntt(f, false), ntt(g, false);
    FOR(i, 2 * n) f[i] *= g[i];
    ntt(f, true);
    FOR(i, n) f[i] = 0;
    ntt(f, false);
    FOR(i, 2 * n) f[i] *= g[i];
    ntt(f, true);
    FOR(i, n, min(N, 2 * n)) G.eb(-f[i]);
    n *= 2;
  }
  return G;
}

template <typename mint>
vc<mint> fps_inv_dense(const vc<mint>& F) {
  return fps_inv_dense_ntt(F);
}

template <typename mint>
vc<mint> fps_inv(const vc<mint>& f) {
  assert(f[0] != mint(0));
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 160 : 820);
  return (n <= t ? fps_inv_sparse<mint>(f) : fps_inv_dense<mint>(f));
}

// f/g. f の長さで出力される.
template <typename mint, bool SPARSE = false>
vc<mint> fps_div(vc<mint> f, vc<mint> g) {
  if (SPARSE || count_terms(g) < 200) return fps_div_sparse(f, g);
  int n = len(f);
  g.resize(n);
  g = fps_inv<mint>(g);
  f = convolution(f, g);
  f.resize(n);
  return f;
}

// f/g ただし g は sparse
template <typename mint>
vc<mint> fps_div_sparse(vc<mint> f, vc<mint>& g) {
  if (g[0] != mint(1)) {
    mint cf = g[0].inverse();
    for (auto&& x: f) x *= cf;
    for (auto&& x: g) x *= cf;
  }

  vc<pair<int, mint>> dat;
  FOR(i, 1, len(g)) if (g[i] != mint(0)) dat.eb(i, -g[i]);
  FOR(i, len(f)) {
    for (auto&& [j, x]: dat) {
      if (i >= j) f[i] += x * f[i - j];
    }
  }
  return f;
}

// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
vc<mint> integrate(const vc<mint>& f) {
  vc<mint> g(len(f) + 1);
  FOR3(i, 1, len(g)) g[i] = f[i - 1] * inv<mint>(i);
  return g;
}

// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
mint integrate(const vc<mint>& f, mint L, mint R) {
  mint I = 0;
  mint pow_L = 1, pow_R = 1;
  FOR(i, len(f)) {
    pow_L *= L, pow_R *= R;
    I += inv<mint>(i + 1) * f[i] * (pow_R - pow_L);
  }
  return I;
}

template <typename mint>
vc<mint> fps_exp_sparse(vc<mint>& f) {
  if (len(f) == 0) return {mint(1)};
  assert(f[0] == 0);
  int N = len(f);
  // df を持たせる
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i - 1, mint(i) * f[i]);
  vc<mint> F(N);
  F[0] = 1;
  FOR(n, 1, N) {
    mint rhs = 0;
    for (auto&& [k, fk]: dat) {
      if (k > n - 1) break;
      rhs += fk * F[n - 1 - k];
    }
    F[n] = rhs * inv<mint>(n);
  }
  return F;
}

template <typename mint>
vc<mint> fps_exp_dense(vc<mint>& h) {
  const int n = len(h);
  assert(n > 0 && h[0] == mint(0));
  if (mint::can_ntt()) {
    vc<mint>& f = h;
    vc<mint> b = {1, (1 < n ? f[1] : 0)};
    vc<mint> c = {1}, z1, z2 = {1, 1};
    while (len(b) < n) {
      int m = len(b);
      auto y = b;
      y.resize(2 * m);
      ntt(y, 0);
      z1 = z2;
      vc<mint> z(m);
      FOR(i, m) z[i] = y[i] * z1[i];
      ntt(z, 1);
      FOR(i, m / 2) z[i] = 0;
      ntt(z, 0);
      FOR(i, m) z[i] *= -z1[i];
      ntt(z, 1);
      c.insert(c.end(), z.begin() + m / 2, z.end());
      z2 = c;
      z2.resize(2 * m);
      ntt(z2, 0);

      vc<mint> x(f.begin(), f.begin() + m);
      FOR(i, len(x) - 1) x[i] = x[i + 1] * mint(i + 1);
      x.back() = 0;
      ntt(x, 0);
      FOR(i, m) x[i] *= y[i];
      ntt(x, 1);

      FOR(i, m - 1) x[i] -= b[i + 1] * mint(i + 1);

      x.resize(m + m);
      FOR(i, m - 1) x[m + i] = x[i], x[i] = 0;
      ntt(x, 0);
      FOR(i, m + m) x[i] *= z2[i];
      ntt(x, 1);
      FOR_R(i, len(x) - 1) x[i + 1] = x[i] * inv<mint>(i + 1);
      x[0] = 0;

      FOR3(i, m, min(n, m + m)) x[i] += f[i];
      FOR(i, m) x[i] = 0;
      ntt(x, 0);
      FOR(i, m + m) x[i] *= y[i];
      ntt(x, 1);
      b.insert(b.end(), x.begin() + m, x.end());
    }
    b.resize(n);
    return b;
  }

  const int L = len(h);
  assert(L > 0 && h[0] == mint(0));
  int LOG = 0;
  while (1 << LOG < L) ++LOG;
  h.resize(1 << LOG);
  auto dh = differentiate(h);
  vc<mint> f = {1}, g = {1};
  int m = 1;

  vc<mint> p;

  FOR(LOG) {
    p = convolution(f, g);
    p.resize(m);
    p = convolution(p, g);
    p.resize(m);
    g.resize(m);
    FOR(i, m) g[i] += g[i] - p[i];
    p = {dh.begin(), dh.begin() + m - 1};
    p = convolution(f, p);
    p.resize(m + m - 1);
    FOR(i, m + m - 1) p[i] = -p[i];
    FOR(i, m - 1) p[i] += mint(i + 1) * f[i + 1];
    p = convolution(p, g);

    p.resize(m + m - 1);
    FOR(i, m - 1) p[i] += dh[i];
    p = integrate(p);
    FOR(i, m + m) p[i] = h[i] - p[i];
    p[0] += mint(1);
    f = convolution(f, p);
    f.resize(m + m);
    m += m;
  }
  f.resize(L);
  return f;
}

template <typename mint>
vc<mint> fps_exp(vc<mint>& f) {
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 320 : 3000);
  return (n <= t ? fps_exp_sparse<mint>(f) : fps_exp_dense<mint>(f));
}

template <typename mint>
vc<mint> fps_log_dense(const vc<mint>& f) {
  assert(f[0] == mint(1));
  ll N = len(f);
  vc<mint> df = f;
  FOR(i, N) df[i] *= mint(i);
  df.erase(df.begin());
  auto f_inv = fps_inv(f);
  auto g = convolution(df, f_inv);
  g.resize(N - 1);
  g.insert(g.begin(), 0);
  FOR(i, N) g[i] *= inv<mint>(i);
  return g;
}

template <typename mint>
vc<mint> fps_log_sparse(const vc<mint>& f) {
  int N = f.size();
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> F(N);
  vc<mint> g(N - 1);
  for (int n = 0; n < N - 1; ++n) {
    mint rhs = mint(n + 1) * f[n + 1];
    for (auto&& [i, fi]: dat) {
      if (i > n) break;
      rhs -= fi * g[n - i];
    }
    g[n] = rhs;
    F[n + 1] = rhs * inv<mint>(n + 1);
  }
  return F;
}

template <typename mint>
vc<mint> fps_log(const vc<mint>& f) {
  assert(f[0] == mint(1));
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 200 : 1200);
  return (n <= t ? fps_log_sparse<mint>(f) : fps_log_dense<mint>(f));
}

// fps の k 乗を求める。k >= 0 の前提である。
// 定数項が 1 で、k が mint の場合には、fps_pow_1 を使うこと。
// ・dense な場合: log, exp を使う O(NlogN)
// ・sparse な場合: O(NK)
template <typename mint>
vc<mint> fps_pow(const vc<mint>& f, ll k) {
  assert(0 <= k);
  int n = len(f);
  if (k == 0) {
    vc<mint> g(n);
    g[0] = mint(1);
    return g;
  }
  int d = n;
  FOR_R(i, n) if (f[i] != 0) d = i;
  // d * k >= n
  if (d >= ceil<ll>(n, k)) {
    vc<mint> g(n);
    return g;
  }
  ll off = d * k;
  mint c = f[d];
  mint c_inv = mint(1) / mint(c);
  vc<mint> g(n - off);
  FOR(i, n - off) g[i] = f[d + i] * c_inv;
  g = fps_pow_1(g, mint(k));
  vc<mint> h(n);
  c = c.pow(k);
  FOR(i, len(g)) h[off + i] = g[i] * c;
  return h;
}

template <typename mint>
vc<mint> fps_pow_1_sparse(const vc<mint>& f, mint K) {
  int N = len(f);
  assert(N == 0 || f[0] == mint(1));
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> g(N);
  g[0] = 1;
  FOR(n, N - 1) {
    mint& x = g[n + 1];
    for (auto&& [d, cf]: dat) {
      if (d > n + 1) break;
      mint t = cf * g[n - d + 1];
      x += t * (K * mint(d) - mint(n - d + 1));
    }
    x *= inv<mint>(n + 1);
  }
  return g;
}

template <typename mint>
vc<mint> fps_pow_1_dense(const vc<mint>& f, mint K) {
  assert(f[0] == mint(1));
  auto log_f = fps_log(f);
  FOR(i, len(f)) log_f[i] *= K;
  return fps_exp_dense(log_f);
}

template <typename mint>
vc<mint> fps_pow_1(const vc<mint>& f, mint K) {
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 100 : 1300);
  return (n <= t ? fps_pow_1_sparse(f, K) : fps_pow_1_dense(f, K));
}

// f^e, sparse, O(NMK)
template <typename mint>
vvc<mint> fps_pow_1_sparse_2d(vvc<mint> f, mint n) {
  assert(f[0][0] == mint(1));
  int N = len(f), M = len(f[0]);
  vv(mint, dp, N, M);
  dp[0] = fps_pow_1_sparse<mint>(f[0], n);

  vc<tuple<int, int, mint>> dat;
  FOR(i, N) FOR(j, M) {
    if ((i > 0 || j > 0) && f[i][j] != mint(0)) dat.eb(i, j, f[i][j]);
  }
  FOR(i, 1, N) {
    FOR(j, M) {
      // F = f^n, f dF = n df F
      // [x^{i-1}y^j]
      mint lhs = 0, rhs = 0;
      for (auto&& [a, b, c]: dat) {
        if (a < i && b <= j) lhs += dp[i - a][j - b] * mint(i - a);
        if (a <= i && b <= j) rhs += dp[i - a][j - b] * c * mint(a);
      }
      dp[i][j] = (n * rhs - lhs) * inv<mint>(i);
    }
  }
  return dp;
}

// k を固定して [x^k]f(x)^ig(x) を i=0,1,...,n で求める.
template <typename mint>
vc<mint> coef_of_fps_pows(vc<mint> f, int k, int n, vc<mint> g = {mint(1)}) {
  assert(len(f) == k + 1);
  vv(mint, P, k + 1, 2);
  vv(mint, Q, k + 1, 2);
  Q[0][0] = 1;
  FOR(i, len(g)) if (i <= k) P[i][0] = g[i];
  FOR(i, len(f)) if (i <= k) Q[i][1] = -f[i];
  FOR(i, len(f)) Q[i][1] = -f[i];

  while (k > 0) {
    int H = len(P), W = len(P[0]);
    vvc<mint> R = Q;
    FOR(i, H) {
      if (i % 2 == 0) continue;
      FOR(j, W) { R[i][j] = -R[i][j]; }
    }
    vvc<mint> F = convolution2d<mint>(P, R);
    vvc<mint> G = convolution2d<mint>(Q, R);
    P.resize(k / 2 + 1);
    Q.resize(k / 2 + 1);
    FOR(i, len(P)) P[i] = F[2 * i | (k & 1)];
    FOR(i, len(Q)) Q[i] = G[2 * i];
    k /= 2;
    FOR(i, len(P)) if (len(P[i]) > n + 1) P[i].resize(n + 1);
    FOR(i, len(Q)) if (len(Q[i]) > n + 1) Q[i].resize(n + 1);
  }
  vc<mint> F = P[0], G = Q[0];
  F.resize(n + 1), G.resize(n + 1);
  return fps_div<mint>(F, G);
}

// O(Nlog^2N)
template <typename mint>
vc<mint> compositional_inverse(vc<mint> f) {
  /*
  仮定:[x^1]f = c は 0 ではない.
  f を改めて cf と書く. f の逆関数を g とすれば
  g(cf(x)/c)=x なので g(x/c) が求めるもの.よって [x^1]f=1 に帰着.

  f, g は n 次とする. Lagrange inversion formula
  n[x^n]f(x)^i = [x^{n-i}] i(g(x)/x)^{-n}
  左辺を i=1,...,n で求めると (g(x)/x)^{-n} が n-1 次まで求まる.
  [x^1]g=1 に帰着していたので -1/n 乗根がとれて, g(x)/x が n-1 次まで求まる.
  */
  const int n = len(f) - 1;
  if (n == -1) return {};
  assert(f[0] == mint(0));
  if (n == 0) return f;
  assert(f[1] != mint(0));
  mint c = f[1];
  for (auto& x: f) x /= c;

  vc<mint> A = coef_of_fps_pows<mint>(f, n, n);
  vc<mint> g(n);
  FOR(i, 1, n + 1) g[n - i] = mint(n) * A[i] * inv<mint>(i);
  g = fps_pow_1<mint>(g, -inv<mint>(n));
  g.insert(g.begin(), 0);

  mint pow = 1;
  FOR(i, len(g)) g[i] *= pow, pow /= c;
  return g;
}

template <typename mint>
vc<mint> middle_product(vc<mint> &a, vc<mint> &b) {
  assert(len(a) >= len(b));
  if (b.empty()) return vc<mint>(len(a) - len(b) + 1);
  if (min(len(b), len(a) - len(b) + 1) <= 60) {
    return middle_product_naive(a, b);
  }
  int n = 1 << topbit(2 * len(a) - 1);
  vc<mint> fa(n), fb(n);
  copy(a.begin(), a.end(), fa.begin());
  copy(b.rbegin(), b.rend(), fb.begin());
  ntt(fa, 0), ntt(fb, 0);
  FOR(i, n) fa[i] *= fb[i];
  ntt(fa, 1);
  fa.resize(len(a));
  fa.erase(fa.begin(), fa.begin() + len(b) - 1);
  return fa;
}

template <typename mint>
vc<mint> middle_product_naive(vc<mint> &a, vc<mint> &b) {
  vc<mint> res(len(a) - len(b) + 1);
  FOR(i, len(res)) FOR(j, len(b)) res[i] += b[j] * a[i + j];
  return res;
}

// O(Nlog^2N)
template <typename mint>
vc<mint> composition(vc<mint> f, vc<mint> g) {
  // 必要ではないが簡略化のために,[x^0]g=0 に帰着しておく.
  const int N = len(f) - 1;
  assert(len(f) == N + 1 && len(g) == N + 1);
  if (N == -1) return {};
  mint c = g[0];
  g[0] = 0;
  f = poly_taylor_shift<mint>(f, c);

  auto degree = [&](vvc<mint> &F) -> pair<int, int> {
    return {len(F) - 1, len(F[0]) - 1};
  };

  /*
  f, g は N 次とする.
  合成は (f_i) -> sum_i f_ig(x)^i である. これの転置を考える.
  (h_j) に対して [x^0]h(x^-1)sum_if_ig(x)^i = sum_if_i[x^0]h(x^{-1})g(x)^i
  であるから [x^N]rev_h(x)g(x)^i を計算するというのが転置である.
  したがって合成は [x^N]rev_h(x)g(x)^i 列挙の転置をとれば計算できる.

  転置問題は, 次のような反復により解ける:
  ・入力を reverse する.
  ・次を k=0,1,2,...,K で繰り返す(K=lg n 程度).
   ・g だけから定まる何らかの G_k(x,y) と畳み込む
   ・適切な部分を抜き出す

  よって合成は次の計算による
  ・次を k=m,...,2,1,0 で繰り返す
   ・適切な部分に入れる
   ・G_k(x,y) との畳み込みの転置でうつす
  ・reverse して出力する.

  G_k(x,y) は k の昇順に計算できて,これを逆順に処理するため,
  ここでは再帰関数により実装する.
  */
  auto dfs = [&](auto &dfs, vvc<mint> G) -> vvc<mint> {
    auto [n, m] = degree(G);
    if (n == 0) {
      // [x^0]g=0 としていたので G=1 である.
      // 転置問題ではこの時点での多項式がそのまま出力となる.
      // よって入力をそのまま多項式に入れて返す.
      vv(mint, F, n + 1, m + 1);
      FOR(j, len(f)) F[0][j] = f[j];
      return F;
    }
    vvc<mint> G1 = G;
    FOR(i, n + 1) {
      if (i % 2 == 0) continue;
      FOR(j, m + 1) G1[i][j] = -G[i][j];
    }
    vvc<mint> G2 = convolution2d(G, G1);
    int n2 = n / 2;
    FOR(i, n2 + 1) G2[i] = G2[2 * i];
    G2.resize(n2 + 1);
    vvc<mint> F = dfs(dfs, G2);
    assert(degree(F) == degree(G2));
    // 転置問題では G1 と畳み込んだあと n の parity に応じた部分を抜き出す.
    // よってまず dfs の出力を抜き出す前の位置に入れて, 畳み込みの転置をとる.

    // 畳み込みの転置をとるとは何なのか.
    // (n,m) 次の多項式積 H(x,y) G(x,y)
    // H, G を適切に配置した (n+1)(2m+1)-1 次多項式を用意して
    // 畳み込んで 2(n+1)(2m+1)-2 次多項式を得る.
    // この適切な (2n,2m) 次多項式を抜き出す.
    // 転置をとると次のようになる.
    // F を適切に配置した (2n,2m) 次多項式を作る.
    // ここから 2(n+1)(2m+1)-2 次多項式を作る.
    // これと適切な多項式の middle product をとって
    // (n+1)(2m+1)-1 次多項式を得る.
    vc<mint> A(2 * (n + 1) * (2 * m + 1) - 1);
    FOR(i, len(F)) FOR(j, len(F[0])) {
      int i1 = 2 * i + (n % 2);
      int idx = i1 * (2 * m + 1) + j;
      A[idx] = F[i][j];
    }
    vc<mint> B((n + 1) * (2 * m + 1));
    FOR(i, n + 1) FOR(j, m + 1) {
      int idx = i * (2 * m + 1) + j;
      B[idx] = G1[i][j];
    }

    A = middle_product<mint>(A, B);
    assert(len(A) == (n + 1) * (2 * m + 1));
    vv(mint, res, n + 1, m + 1);
    FOR(i, n + 1) FOR(j, m + 1) {
      int idx = (2 * m + 1) * i + j;
      res[i][j] = A[idx];
    }
    return res;
  };
  vv(mint, G, N + 1, 2);
  G[0][0] = 1;
  FOR(i, N + 1) G[i][1] = -g[i];
  vvc<mint> F = dfs(dfs, G);
  assert(degree(F) == (pair<int, int>{N, 1}));
  vc<mint> ANS(N + 1);
  FOR(i, N + 1) ANS[i] = F[i][0];
  // 最後に reverse する
  reverse(all(ANS));
  return ANS;
}

using coefficient = modint998;

} // namespace formal_power_series_composition_internal

/// @brief Compose two formal power series modulo x^n over 998244353.
/// After shifting away g(0), transposition turns composition into simultaneous
/// coefficient extraction from powers of g. A bivariate Bostan-Mori recursion
/// halves the x degree at every level; reversing that recursion applies the
/// transposed two-dimensional convolutions and reconstructs all coefficients.
inline std::vector<std::uint32_t> formal_power_series_composition_998244353(
    const std::vector<std::uint32_t> &outer,
    const std::vector<std::uint32_t> &inner) {
  assert(outer.size() == inner.size());
  using namespace formal_power_series_composition_internal;
  vc<coefficient> f(outer.begin(), outer.end());
  vc<coefficient> g(inner.begin(), inner.end());
  f = composition<coefficient>(std::move(f), std::move(g));
  std::vector<std::uint32_t> result(f.size());
  for (int i = 0; i < int(f.size()); i++) {
    result[i] = f[i].val;
  }
  return result;
}

/// @brief Invert a formal power series under composition over 998244353.
/// Lagrange inversion expresses the coefficients of the inverse through one
/// diagonal of powers of f. Bivariate Bostan-Mori extracts that diagonal in
/// O(n log^2 n); a formal (-1/n)-th power then recovers g(x)/x, followed by the
/// linear-coefficient rescaling that was normalized at the start.
inline std::vector<std::uint32_t>
formal_power_series_compositional_inverse_998244353(
    const std::vector<std::uint32_t> &series) {
  using namespace formal_power_series_composition_internal;
  vc<coefficient> f(series.begin(), series.end());
  f = compositional_inverse<coefficient>(std::move(f));
  std::vector<std::uint32_t> result(f.size());
  for (int i = 0; i < int(f.size()); i++) {
    result[i] = f[i].val;
  }
  return result;
}

} // namespace noya

#undef vv
#undef FOR1
#undef FOR2
#undef FOR3
#undef FOR4
#undef FOR1_R
#undef FOR2_R
#undef FOR3_R
#undef overload4
#undef overload3
#undef FOR
#undef FOR_R
#undef all
#undef len
#undef elif
#undef eb
#undef mp
#undef mt
#undef fi
#undef se

#endif // NOYA_FORMAL_POWER_SERIES_COMPOSITION_HPP
#include <algorithm>
#include <array>
#include <cassert>
#include <cstdint>
#include <utility>
#include <vector>

/// @complexity Time: O(n log^2 n). Space: O(n log n).

namespace noya {

namespace formal_power_series_composition_internal {

using namespace std;

using ll = long long;
using u32 = unsigned int;
using u64 = unsigned long long;

using pi = pair<ll, ll>;
template <class T>
using vc = vector<T>;
template <class T>
using vvc = vector<vc<T>>;

#define vv(type, name, h, ...) \
  vector<vector<type>> name(h, vector<type>(__VA_ARGS__))

#define FOR1(a) for (ll _ = 0; _ < ll(a); ++_)
#define FOR2(i, a) for (ll i = 0; i < ll(a); ++i)
#define FOR3(i, a, b) for (ll i = a; i < ll(b); ++i)
#define FOR4(i, a, b, c) for (ll i = a; i < ll(b); i += (c))
#define FOR1_R(a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR2_R(i, a) for (ll i = (a)-1; i >= ll(0); --i)
#define FOR3_R(i, a, b) for (ll i = (b)-1; i >= ll(a); --i)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FOR_R(...) overload3(__VA_ARGS__, FOR3_R, FOR2_R, FOR1_R)(__VA_ARGS__)

#define all(x) x.begin(), x.end()
#define len(x) ll(x.size())
#define elif else if

#define eb emplace_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second

// (0, 1, 2, 3, 4) -> (-1, 0, 1, 1, 2)
inline int topbit(int x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
inline int topbit(u32 x) { return (x == 0 ? -1 : 31 - __builtin_clz(x)); }
inline int topbit(ll x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }
inline int topbit(u64 x) { return (x == 0 ? -1 : 63 - __builtin_clzll(x)); }

template <typename T>
T floor(T a, T b) {
  return a / b - (a % b && (a ^ b) < 0);
}
template <typename T>
T ceil(T x, T y) {
  return floor(x + y - 1, y);
}

template <typename mint>
mint inv(int n) {
  static const int mod = mint::get_mod();
  static vector<mint> dat = {0, 1};
  assert(0 <= n);
  if (n >= mod) n %= mod;
  while (len(dat) <= n) {
    int k = len(dat);
    int q = (mod + k - 1) / k;
    dat.eb(dat[k * q - mod] * mint::raw(q));
  }
  return dat[n];
}

template <typename mint>
mint fact(int n) {
  static const int mod = mint::get_mod();
  assert(0 <= n && n < mod);
  static vector<mint> dat = {1, 1};
  while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * mint::raw(len(dat)));
  return dat[n];
}

template <typename mint>
mint fact_inv(int n) {
  static vector<mint> dat = {1, 1};
  if (n < 0) return mint(0);
  while (len(dat) <= n) dat.eb(dat[len(dat) - 1] * inv<mint>(len(dat)));
  return dat[n];
}

template <int mod>
struct modint {
  static constexpr u32 umod = u32(mod);
  static_assert(umod < u32(1) << 31);
  u32 val;

  static modint raw(u32 v) {
    modint x;
    x.val = v;
    return x;
  }
  constexpr modint() : val(0) {}
  constexpr modint(u32 x) : val(x % umod) {}
  constexpr modint(u64 x) : val(x % umod) {}
  constexpr modint(int x) : val((x %= mod) < 0 ? x + mod : x){};
  constexpr modint(ll x) : val((x %= mod) < 0 ? x + mod : x){};
  bool operator<(const modint& other) const { return val < other.val; }
  modint& operator+=(const modint& p) {
    if ((val += p.val) >= umod) val -= umod;
    return *this;
  }
  modint& operator-=(const modint& p) {
    if ((val += umod - p.val) >= umod) val -= umod;
    return *this;
  }
  modint& operator*=(const modint& p) {
    val = u64(val) * p.val % umod;
    return *this;
  }
  modint& operator/=(const modint& p) {
    *this *= p.inverse();
    return *this;
  }
  modint operator-() const { return modint::raw(val ? mod - val : u32(0)); }
  modint operator+(const modint& p) const { return modint(*this) += p; }
  modint operator-(const modint& p) const { return modint(*this) -= p; }
  modint operator*(const modint& p) const { return modint(*this) *= p; }
  modint operator/(const modint& p) const { return modint(*this) /= p; }
  bool operator==(const modint& p) const { return val == p.val; }
  bool operator!=(const modint& p) const { return val != p.val; }
  modint inverse() const {
    int a = val, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b), swap(u -= t * v, v);
    }
    return modint(u);
  }
  modint pow(ll n) const {
    assert(n >= 0);
    modint ret(1), mul(val);
    while (n > 0) {
      if (n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
  static constexpr int get_mod() { return mod; }
  // (n, r), r は 1 の 2^n 乗根
  static constexpr pair<int, int> ntt_info() {
    if (mod == 998244353) return {23, 31};
    return {-1, -1};
  }
  static constexpr bool can_ntt() { return ntt_info().fi != -1; }
};

using modint998 = modint<998244353>;

template <typename mint>
vc<mint> differentiate(const vc<mint>& f) {
  if (len(f) <= 1) return {};
  vc<mint> g(len(f) - 1);
  FOR(i, len(g)) g[i] = f[i + 1] * mint(i + 1);
  return g;
}

template <class T>
vc<T> convolution_naive(const vc<T>& a, const vc<T>& b) {
  int n = int(a.size()), m = int(b.size());
  if (n > m) return convolution_naive<T>(b, a);
  if (n == 0) return {};
  vc<T> ans(n + m - 1);
  if (n <= 16 && (T::get_mod() < (1 << 30))) {
    for (int k = 0; k < n + m - 1; ++k) {
      int s = max(0, k - m + 1);
      int t = min(n, k + 1);
      u64 sm = 0;
      for (int i = s; i < t; ++i) { sm += u64(a[i].val) * (b[k - i].val); }
      ans[k] = sm;
    }
  } else {
    FOR(i, n) FOR(j, m) ans[i + j] += a[i] * b[j];
  }
  return ans;
}

// 任意の環でできる
template <typename T>
vc<T> convolution_karatsuba(const vc<T>& f, const vc<T>& g) {
  const int thresh = 30;
  if (min(len(f), len(g)) <= thresh) return convolution_naive(f, g);
  int n = max(len(f), len(g));
  int m = ceil(n, 2);
  vc<T> f1, f2, g1, g2;
  if (len(f) < m) f1 = f;
  if (len(f) >= m) f1 = {f.begin(), f.begin() + m};
  if (len(f) >= m) f2 = {f.begin() + m, f.end()};
  if (len(g) < m) g1 = g;
  if (len(g) >= m) g1 = {g.begin(), g.begin() + m};
  if (len(g) >= m) g2 = {g.begin() + m, g.end()};
  vc<T> a = convolution_karatsuba(f1, g1);
  vc<T> b = convolution_karatsuba(f2, g2);
  FOR(i, len(f2)) f1[i] += f2[i];
  FOR(i, len(g2)) g1[i] += g2[i];
  vc<T> c = convolution_karatsuba(f1, g1);
  vc<T> F(len(f) + len(g) - 1);
  assert(2 * m + len(b) <= len(F));
  FOR(i, len(a)) F[i] += a[i], c[i] -= a[i];
  FOR(i, len(b)) F[2 * m + i] += b[i], c[i] -= b[i];
  if (c.back() == T(0)) c.pop_back();
  FOR(i, len(c)) if (c[i] != T(0)) F[m + i] += c[i];
  return F;
}

template <class mint>
void ntt(vector<mint>& a, bool inverse) {
  assert(mint::can_ntt());
  const int rank2 = mint::ntt_info().fi;
  const int mod = mint::get_mod();
  static array<mint, 30> root, iroot;
  static array<mint, 30> rate2, irate2;
  static array<mint, 30> rate3, irate3;

  assert(rank2 != -1 && len(a) <= (1 << max(0, rank2)));

  static bool prepared = 0;
  if (!prepared) {
    prepared = 1;
    root[rank2] = mint::ntt_info().se;
    iroot[rank2] = mint(1) / root[rank2];
    FOR_R(i, rank2) {
      root[i] = root[i + 1] * root[i + 1];
      iroot[i] = iroot[i + 1] * iroot[i + 1];
    }
    mint prod = 1, iprod = 1;
    for (int i = 0; i <= rank2 - 2; i++) {
      rate2[i] = root[i + 2] * prod;
      irate2[i] = iroot[i + 2] * iprod;
      prod *= iroot[i + 2];
      iprod *= root[i + 2];
    }
    prod = 1, iprod = 1;
    for (int i = 0; i <= rank2 - 3; i++) {
      rate3[i] = root[i + 3] * prod;
      irate3[i] = iroot[i + 3] * iprod;
      prod *= iroot[i + 3];
      iprod *= root[i + 3];
    }
  }

  int n = int(a.size());
  int h = topbit(n);
  assert(n == 1 << h);
  if (!inverse) {
    int len = 0;
    while (len < h) {
      if (h - len == 1) {
        int p = 1 << (h - len - 1);
        mint rot = 1;
        FOR(s, 1 << len) {
          int offset = s << (h - len);
          FOR(i, p) {
            auto l = a[i + offset];
            auto r = a[i + offset + p] * rot;
            a[i + offset] = l + r;
            a[i + offset + p] = l - r;
          }
          rot *= rate2[topbit(~s & -~s)];
        }
        len++;
      } else {
        int p = 1 << (h - len - 2);
        mint rot = 1, imag = root[2];
        for (int s = 0; s < (1 << len); s++) {
          mint rot2 = rot * rot;
          mint rot3 = rot2 * rot;
          int offset = s << (h - len);
          for (int i = 0; i < p; i++) {
            u64 mod2 = u64(mod) * mod;
            u64 a0 = a[i + offset].val;
            u64 a1 = u64(a[i + offset + p].val) * rot.val;
            u64 a2 = u64(a[i + offset + 2 * p].val) * rot2.val;
            u64 a3 = u64(a[i + offset + 3 * p].val) * rot3.val;
            u64 a1na3imag = (a1 + mod2 - a3) % mod * imag.val;
            u64 na2 = mod2 - a2;
            a[i + offset] = a0 + a2 + a1 + a3;
            a[i + offset + 1 * p] = a0 + a2 + (2 * mod2 - (a1 + a3));
            a[i + offset + 2 * p] = a0 + na2 + a1na3imag;
            a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
          }
          rot *= rate3[topbit(~s & -~s)];
        }
        len += 2;
      }
    }
  } else {
    mint coef = mint(1) / mint(len(a));
    FOR(i, len(a)) a[i] *= coef;
    int len = h;
    while (len) {
      if (len == 1) {
        int p = 1 << (h - len);
        mint irot = 1;
        FOR(s, 1 << (len - 1)) {
          int offset = s << (h - len + 1);
          FOR(i, p) {
            u64 l = a[i + offset].val;
            u64 r = a[i + offset + p].val;
            a[i + offset] = l + r;
            a[i + offset + p] = (mod + l - r) * irot.val;
          }
          irot *= irate2[topbit(~s & -~s)];
        }
        len--;
      } else {
        int p = 1 << (h - len);
        mint irot = 1, iimag = iroot[2];
        FOR(s, (1 << (len - 2))) {
          mint irot2 = irot * irot;
          mint irot3 = irot2 * irot;
          int offset = s << (h - len + 2);
          for (int i = 0; i < p; i++) {
            u64 a0 = a[i + offset + 0 * p].val;
            u64 a1 = a[i + offset + 1 * p].val;
            u64 a2 = a[i + offset + 2 * p].val;
            u64 a3 = a[i + offset + 3 * p].val;
            u64 x = (mod + a2 - a3) * iimag.val % mod;
            a[i + offset] = a0 + a1 + a2 + a3;
            a[i + offset + 1 * p] = (a0 + mod - a1 + x) * irot.val;
            a[i + offset + 2 * p] = (a0 + a1 + 2 * mod - a2 - a3) * irot2.val;
            a[i + offset + 3 * p] = (a0 + 2 * mod - a1 - x) * irot3.val;
          }
          irot *= irate3[topbit(~s & -~s)];
        }
        len -= 2;
      }
    }
  }
}

template <class mint>
vector<mint> convolution_ntt(vector<mint> a, vector<mint> b) {
  if (a.empty() || b.empty()) return {};
  int n = int(a.size()), m = int(b.size());
  int sz = 1;
  while (sz < n + m - 1) sz *= 2;

  // sz = 2^k のときの高速化。分割統治的なやつで損しまくるので。
  if ((n + m - 3) <= sz / 2) {
    auto a_last = a.back(), b_last = b.back();
    a.pop_back(), b.pop_back();
    auto c = convolution(a, b);
    c.resize(n + m - 1);
    c[n + m - 2] = a_last * b_last;
    FOR(i, len(a)) c[i + len(b)] += a[i] * b_last;
    FOR(i, len(b)) c[i + len(a)] += b[i] * a_last;
    return c;
  }

  a.resize(sz), b.resize(sz);
  bool same = a == b;
  ntt(a, 0);
  if (same) {
    b = a;
  } else {
    ntt(b, 0);
  }
  FOR(i, sz) a[i] *= b[i];
  ntt(a, 1);
  a.resize(n + m - 1);
  return a;
}

template <typename mint>
vc<mint> convolution(const vc<mint>& a, const vc<mint>& b) {
  int n = len(a), m = len(b);
  if (!n || !m) return {};
  if (min(n, m) <= 50) return convolution_karatsuba<mint>(a, b);
  return convolution_ntt(a, b);
}

template <typename T>
vc<vc<T>> convolution2d(vc<vc<T>>& f, vc<vc<T>>& g) {
  auto shape = [&](vc<vc<T>>& f) -> pi {
    ll H = len(f);
    ll W = (H == 0 ? 0 : len(f[0]));
    return {H, W};
  };
  auto [H1, W1] = shape(f);
  auto [H2, W2] = shape(g);
  ll H = H1 + H2 - 1;
  ll W = W1 + W2 - 1;

  vc<T> ff(H1 * W);
  vc<T> gg(H2 * W);
  FOR(x, H1) FOR(y, W1) ff[W * x + y] = f[x][y];
  FOR(x, H2) FOR(y, W2) gg[W * x + y] = g[x][y];
  auto hh = convolution(ff, gg);
  vc<vc<T>> h(H, vc<T>(W));
  FOR(x, H) FOR(y, W) h[x][y] = hh[W * x + y];
  return h;
}

// a^0, ..., a^N
template <typename mint>
vc<mint> powertable_1(mint a, ll N) {
  // table of a^i
  vc<mint> f(N + 1, 1);
  FOR(i, N) f[i + 1] = a * f[i];
  return f;
}

// f(x) -> f(x+c)
template <typename mint>
vc<mint> poly_taylor_shift(vc<mint> f, mint c) {
  ll N = len(f);
  FOR(i, N) f[i] *= fact<mint>(i);
  auto b = powertable_1<mint>(c, N);
  FOR(i, N) b[i] *= fact_inv<mint>(i);
  reverse(all(f));
  f = convolution(f, b);
  f.resize(N);
  reverse(all(f));
  FOR(i, N) f[i] *= fact_inv<mint>(i);
  return f;
}

template <typename mint>
int count_terms(const vc<mint>& f) {
  int t = 0;
  FOR(i, len(f)) if (f[i] != mint(0))++ t;
  return t;
}

template <typename mint>
vc<mint> fps_inv_sparse(const vc<mint>& f) {
  int N = len(f);
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> g(N);
  mint g0 = mint(1) / f[0];
  g[0] = g0;
  FOR(n, 1, N) {
    mint rhs = 0;
    for (auto&& [k, fk]: dat) {
      if (k > n) break;
      rhs -= fk * g[n - k];
    }
    g[n] = rhs * g0;
  }
  return g;
}

template <typename mint>
vc<mint> fps_inv_dense_ntt(const vc<mint>& F) {
  vc<mint> G = {mint(1) / F[0]};
  ll N = len(F), n = 1;
  G.reserve(N);
  while (n < N) {
    vc<mint> f(2 * n), g(2 * n);
    FOR(i, min(N, 2 * n)) f[i] = F[i];
    FOR(i, n) g[i] = G[i];
    ntt(f, false), ntt(g, false);
    FOR(i, 2 * n) f[i] *= g[i];
    ntt(f, true);
    FOR(i, n) f[i] = 0;
    ntt(f, false);
    FOR(i, 2 * n) f[i] *= g[i];
    ntt(f, true);
    FOR(i, n, min(N, 2 * n)) G.eb(-f[i]);
    n *= 2;
  }
  return G;
}

template <typename mint>
vc<mint> fps_inv_dense(const vc<mint>& F) {
  return fps_inv_dense_ntt(F);
}

template <typename mint>
vc<mint> fps_inv(const vc<mint>& f) {
  assert(f[0] != mint(0));
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 160 : 820);
  return (n <= t ? fps_inv_sparse<mint>(f) : fps_inv_dense<mint>(f));
}

// f/g. f の長さで出力される.
template <typename mint, bool SPARSE = false>
vc<mint> fps_div(vc<mint> f, vc<mint> g) {
  if (SPARSE || count_terms(g) < 200) return fps_div_sparse(f, g);
  int n = len(f);
  g.resize(n);
  g = fps_inv<mint>(g);
  f = convolution(f, g);
  f.resize(n);
  return f;
}

// f/g ただし g は sparse
template <typename mint>
vc<mint> fps_div_sparse(vc<mint> f, vc<mint>& g) {
  if (g[0] != mint(1)) {
    mint cf = g[0].inverse();
    for (auto&& x: f) x *= cf;
    for (auto&& x: g) x *= cf;
  }

  vc<pair<int, mint>> dat;
  FOR(i, 1, len(g)) if (g[i] != mint(0)) dat.eb(i, -g[i]);
  FOR(i, len(f)) {
    for (auto&& [j, x]: dat) {
      if (i >= j) f[i] += x * f[i - j];
    }
  }
  return f;
}

// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
vc<mint> integrate(const vc<mint>& f) {
  vc<mint> g(len(f) + 1);
  FOR3(i, 1, len(g)) g[i] = f[i - 1] * inv<mint>(i);
  return g;
}

// 不定積分:integrate(f)
// 定積分:integrate(f, L, R)
template <typename mint>
mint integrate(const vc<mint>& f, mint L, mint R) {
  mint I = 0;
  mint pow_L = 1, pow_R = 1;
  FOR(i, len(f)) {
    pow_L *= L, pow_R *= R;
    I += inv<mint>(i + 1) * f[i] * (pow_R - pow_L);
  }
  return I;
}

template <typename mint>
vc<mint> fps_exp_sparse(vc<mint>& f) {
  if (len(f) == 0) return {mint(1)};
  assert(f[0] == 0);
  int N = len(f);
  // df を持たせる
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i - 1, mint(i) * f[i]);
  vc<mint> F(N);
  F[0] = 1;
  FOR(n, 1, N) {
    mint rhs = 0;
    for (auto&& [k, fk]: dat) {
      if (k > n - 1) break;
      rhs += fk * F[n - 1 - k];
    }
    F[n] = rhs * inv<mint>(n);
  }
  return F;
}

template <typename mint>
vc<mint> fps_exp_dense(vc<mint>& h) {
  const int n = len(h);
  assert(n > 0 && h[0] == mint(0));
  if (mint::can_ntt()) {
    vc<mint>& f = h;
    vc<mint> b = {1, (1 < n ? f[1] : 0)};
    vc<mint> c = {1}, z1, z2 = {1, 1};
    while (len(b) < n) {
      int m = len(b);
      auto y = b;
      y.resize(2 * m);
      ntt(y, 0);
      z1 = z2;
      vc<mint> z(m);
      FOR(i, m) z[i] = y[i] * z1[i];
      ntt(z, 1);
      FOR(i, m / 2) z[i] = 0;
      ntt(z, 0);
      FOR(i, m) z[i] *= -z1[i];
      ntt(z, 1);
      c.insert(c.end(), z.begin() + m / 2, z.end());
      z2 = c;
      z2.resize(2 * m);
      ntt(z2, 0);

      vc<mint> x(f.begin(), f.begin() + m);
      FOR(i, len(x) - 1) x[i] = x[i + 1] * mint(i + 1);
      x.back() = 0;
      ntt(x, 0);
      FOR(i, m) x[i] *= y[i];
      ntt(x, 1);

      FOR(i, m - 1) x[i] -= b[i + 1] * mint(i + 1);

      x.resize(m + m);
      FOR(i, m - 1) x[m + i] = x[i], x[i] = 0;
      ntt(x, 0);
      FOR(i, m + m) x[i] *= z2[i];
      ntt(x, 1);
      FOR_R(i, len(x) - 1) x[i + 1] = x[i] * inv<mint>(i + 1);
      x[0] = 0;

      FOR3(i, m, min(n, m + m)) x[i] += f[i];
      FOR(i, m) x[i] = 0;
      ntt(x, 0);
      FOR(i, m + m) x[i] *= y[i];
      ntt(x, 1);
      b.insert(b.end(), x.begin() + m, x.end());
    }
    b.resize(n);
    return b;
  }

  const int L = len(h);
  assert(L > 0 && h[0] == mint(0));
  int LOG = 0;
  while (1 << LOG < L) ++LOG;
  h.resize(1 << LOG);
  auto dh = differentiate(h);
  vc<mint> f = {1}, g = {1};
  int m = 1;

  vc<mint> p;

  FOR(LOG) {
    p = convolution(f, g);
    p.resize(m);
    p = convolution(p, g);
    p.resize(m);
    g.resize(m);
    FOR(i, m) g[i] += g[i] - p[i];
    p = {dh.begin(), dh.begin() + m - 1};
    p = convolution(f, p);
    p.resize(m + m - 1);
    FOR(i, m + m - 1) p[i] = -p[i];
    FOR(i, m - 1) p[i] += mint(i + 1) * f[i + 1];
    p = convolution(p, g);

    p.resize(m + m - 1);
    FOR(i, m - 1) p[i] += dh[i];
    p = integrate(p);
    FOR(i, m + m) p[i] = h[i] - p[i];
    p[0] += mint(1);
    f = convolution(f, p);
    f.resize(m + m);
    m += m;
  }
  f.resize(L);
  return f;
}

template <typename mint>
vc<mint> fps_exp(vc<mint>& f) {
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 320 : 3000);
  return (n <= t ? fps_exp_sparse<mint>(f) : fps_exp_dense<mint>(f));
}

template <typename mint>
vc<mint> fps_log_dense(const vc<mint>& f) {
  assert(f[0] == mint(1));
  ll N = len(f);
  vc<mint> df = f;
  FOR(i, N) df[i] *= mint(i);
  df.erase(df.begin());
  auto f_inv = fps_inv(f);
  auto g = convolution(df, f_inv);
  g.resize(N - 1);
  g.insert(g.begin(), 0);
  FOR(i, N) g[i] *= inv<mint>(i);
  return g;
}

template <typename mint>
vc<mint> fps_log_sparse(const vc<mint>& f) {
  int N = f.size();
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> F(N);
  vc<mint> g(N - 1);
  for (int n = 0; n < N - 1; ++n) {
    mint rhs = mint(n + 1) * f[n + 1];
    for (auto&& [i, fi]: dat) {
      if (i > n) break;
      rhs -= fi * g[n - i];
    }
    g[n] = rhs;
    F[n + 1] = rhs * inv<mint>(n + 1);
  }
  return F;
}

template <typename mint>
vc<mint> fps_log(const vc<mint>& f) {
  assert(f[0] == mint(1));
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 200 : 1200);
  return (n <= t ? fps_log_sparse<mint>(f) : fps_log_dense<mint>(f));
}

// fps の k 乗を求める。k >= 0 の前提である。
// 定数項が 1 で、k が mint の場合には、fps_pow_1 を使うこと。
// ・dense な場合: log, exp を使う O(NlogN)
// ・sparse な場合: O(NK)
template <typename mint>
vc<mint> fps_pow(const vc<mint>& f, ll k) {
  assert(0 <= k);
  int n = len(f);
  if (k == 0) {
    vc<mint> g(n);
    g[0] = mint(1);
    return g;
  }
  int d = n;
  FOR_R(i, n) if (f[i] != 0) d = i;
  // d * k >= n
  if (d >= ceil<ll>(n, k)) {
    vc<mint> g(n);
    return g;
  }
  ll off = d * k;
  mint c = f[d];
  mint c_inv = mint(1) / mint(c);
  vc<mint> g(n - off);
  FOR(i, n - off) g[i] = f[d + i] * c_inv;
  g = fps_pow_1(g, mint(k));
  vc<mint> h(n);
  c = c.pow(k);
  FOR(i, len(g)) h[off + i] = g[i] * c;
  return h;
}

template <typename mint>
vc<mint> fps_pow_1_sparse(const vc<mint>& f, mint K) {
  int N = len(f);
  assert(N == 0 || f[0] == mint(1));
  vc<pair<int, mint>> dat;
  FOR(i, 1, N) if (f[i] != mint(0)) dat.eb(i, f[i]);
  vc<mint> g(N);
  g[0] = 1;
  FOR(n, N - 1) {
    mint& x = g[n + 1];
    for (auto&& [d, cf]: dat) {
      if (d > n + 1) break;
      mint t = cf * g[n - d + 1];
      x += t * (K * mint(d) - mint(n - d + 1));
    }
    x *= inv<mint>(n + 1);
  }
  return g;
}

template <typename mint>
vc<mint> fps_pow_1_dense(const vc<mint>& f, mint K) {
  assert(f[0] == mint(1));
  auto log_f = fps_log(f);
  FOR(i, len(f)) log_f[i] *= K;
  return fps_exp_dense(log_f);
}

template <typename mint>
vc<mint> fps_pow_1(const vc<mint>& f, mint K) {
  int n = count_terms(f);
  int t = (mint::can_ntt() ? 100 : 1300);
  return (n <= t ? fps_pow_1_sparse(f, K) : fps_pow_1_dense(f, K));
}

// f^e, sparse, O(NMK)
template <typename mint>
vvc<mint> fps_pow_1_sparse_2d(vvc<mint> f, mint n) {
  assert(f[0][0] == mint(1));
  int N = len(f), M = len(f[0]);
  vv(mint, dp, N, M);
  dp[0] = fps_pow_1_sparse<mint>(f[0], n);

  vc<tuple<int, int, mint>> dat;
  FOR(i, N) FOR(j, M) {
    if ((i > 0 || j > 0) && f[i][j] != mint(0)) dat.eb(i, j, f[i][j]);
  }
  FOR(i, 1, N) {
    FOR(j, M) {
      // F = f^n, f dF = n df F
      // [x^{i-1}y^j]
      mint lhs = 0, rhs = 0;
      for (auto&& [a, b, c]: dat) {
        if (a < i && b <= j) lhs += dp[i - a][j - b] * mint(i - a);
        if (a <= i && b <= j) rhs += dp[i - a][j - b] * c * mint(a);
      }
      dp[i][j] = (n * rhs - lhs) * inv<mint>(i);
    }
  }
  return dp;
}

// k を固定して [x^k]f(x)^ig(x) を i=0,1,...,n で求める.
template <typename mint>
vc<mint> coef_of_fps_pows(vc<mint> f, int k, int n, vc<mint> g = {mint(1)}) {
  assert(len(f) == k + 1);
  vv(mint, P, k + 1, 2);
  vv(mint, Q, k + 1, 2);
  Q[0][0] = 1;
  FOR(i, len(g)) if (i <= k) P[i][0] = g[i];
  FOR(i, len(f)) if (i <= k) Q[i][1] = -f[i];
  FOR(i, len(f)) Q[i][1] = -f[i];

  while (k > 0) {
    int H = len(P), W = len(P[0]);
    vvc<mint> R = Q;
    FOR(i, H) {
      if (i % 2 == 0) continue;
      FOR(j, W) { R[i][j] = -R[i][j]; }
    }
    vvc<mint> F = convolution2d<mint>(P, R);
    vvc<mint> G = convolution2d<mint>(Q, R);
    P.resize(k / 2 + 1);
    Q.resize(k / 2 + 1);
    FOR(i, len(P)) P[i] = F[2 * i | (k & 1)];
    FOR(i, len(Q)) Q[i] = G[2 * i];
    k /= 2;
    FOR(i, len(P)) if (len(P[i]) > n + 1) P[i].resize(n + 1);
    FOR(i, len(Q)) if (len(Q[i]) > n + 1) Q[i].resize(n + 1);
  }
  vc<mint> F = P[0], G = Q[0];
  F.resize(n + 1), G.resize(n + 1);
  return fps_div<mint>(F, G);
}

// O(Nlog^2N)
template <typename mint>
vc<mint> compositional_inverse(vc<mint> f) {
  /*
  仮定:[x^1]f = c は 0 ではない.
  f を改めて cf と書く. f の逆関数を g とすれば
  g(cf(x)/c)=x なので g(x/c) が求めるもの.よって [x^1]f=1 に帰着.

  f, g は n 次とする. Lagrange inversion formula
  n[x^n]f(x)^i = [x^{n-i}] i(g(x)/x)^{-n}
  左辺を i=1,...,n で求めると (g(x)/x)^{-n} が n-1 次まで求まる.
  [x^1]g=1 に帰着していたので -1/n 乗根がとれて, g(x)/x が n-1 次まで求まる.
  */
  const int n = len(f) - 1;
  if (n == -1) return {};
  assert(f[0] == mint(0));
  if (n == 0) return f;
  assert(f[1] != mint(0));
  mint c = f[1];
  for (auto& x: f) x /= c;

  vc<mint> A = coef_of_fps_pows<mint>(f, n, n);
  vc<mint> g(n);
  FOR(i, 1, n + 1) g[n - i] = mint(n) * A[i] * inv<mint>(i);
  g = fps_pow_1<mint>(g, -inv<mint>(n));
  g.insert(g.begin(), 0);

  mint pow = 1;
  FOR(i, len(g)) g[i] *= pow, pow /= c;
  return g;
}

template <typename mint>
vc<mint> middle_product(vc<mint> &a, vc<mint> &b) {
  assert(len(a) >= len(b));
  if (b.empty()) return vc<mint>(len(a) - len(b) + 1);
  if (min(len(b), len(a) - len(b) + 1) <= 60) {
    return middle_product_naive(a, b);
  }
  int n = 1 << topbit(2 * len(a) - 1);
  vc<mint> fa(n), fb(n);
  copy(a.begin(), a.end(), fa.begin());
  copy(b.rbegin(), b.rend(), fb.begin());
  ntt(fa, 0), ntt(fb, 0);
  FOR(i, n) fa[i] *= fb[i];
  ntt(fa, 1);
  fa.resize(len(a));
  fa.erase(fa.begin(), fa.begin() + len(b) - 1);
  return fa;
}

template <typename mint>
vc<mint> middle_product_naive(vc<mint> &a, vc<mint> &b) {
  vc<mint> res(len(a) - len(b) + 1);
  FOR(i, len(res)) FOR(j, len(b)) res[i] += b[j] * a[i + j];
  return res;
}

// O(Nlog^2N)
template <typename mint>
vc<mint> composition(vc<mint> f, vc<mint> g) {
  // 必要ではないが簡略化のために,[x^0]g=0 に帰着しておく.
  const int N = len(f) - 1;
  assert(len(f) == N + 1 && len(g) == N + 1);
  if (N == -1) return {};
  mint c = g[0];
  g[0] = 0;
  f = poly_taylor_shift<mint>(f, c);

  auto degree = [&](vvc<mint> &F) -> pair<int, int> {
    return {len(F) - 1, len(F[0]) - 1};
  };

  /*
  f, g は N 次とする.
  合成は (f_i) -> sum_i f_ig(x)^i である. これの転置を考える.
  (h_j) に対して [x^0]h(x^-1)sum_if_ig(x)^i = sum_if_i[x^0]h(x^{-1})g(x)^i
  であるから [x^N]rev_h(x)g(x)^i を計算するというのが転置である.
  したがって合成は [x^N]rev_h(x)g(x)^i 列挙の転置をとれば計算できる.

  転置問題は, 次のような反復により解ける:
  ・入力を reverse する.
  ・次を k=0,1,2,...,K で繰り返す(K=lg n 程度).
   ・g だけから定まる何らかの G_k(x,y) と畳み込む
   ・適切な部分を抜き出す

  よって合成は次の計算による
  ・次を k=m,...,2,1,0 で繰り返す
   ・適切な部分に入れる
   ・G_k(x,y) との畳み込みの転置でうつす
  ・reverse して出力する.

  G_k(x,y) は k の昇順に計算できて,これを逆順に処理するため,
  ここでは再帰関数により実装する.
  */
  auto dfs = [&](auto &dfs, vvc<mint> G) -> vvc<mint> {
    auto [n, m] = degree(G);
    if (n == 0) {
      // [x^0]g=0 としていたので G=1 である.
      // 転置問題ではこの時点での多項式がそのまま出力となる.
      // よって入力をそのまま多項式に入れて返す.
      vv(mint, F, n + 1, m + 1);
      FOR(j, len(f)) F[0][j] = f[j];
      return F;
    }
    vvc<mint> G1 = G;
    FOR(i, n + 1) {
      if (i % 2 == 0) continue;
      FOR(j, m + 1) G1[i][j] = -G[i][j];
    }
    vvc<mint> G2 = convolution2d(G, G1);
    int n2 = n / 2;
    FOR(i, n2 + 1) G2[i] = G2[2 * i];
    G2.resize(n2 + 1);
    vvc<mint> F = dfs(dfs, G2);
    assert(degree(F) == degree(G2));
    // 転置問題では G1 と畳み込んだあと n の parity に応じた部分を抜き出す.
    // よってまず dfs の出力を抜き出す前の位置に入れて, 畳み込みの転置をとる.

    // 畳み込みの転置をとるとは何なのか.
    // (n,m) 次の多項式積 H(x,y) G(x,y)
    // H, G を適切に配置した (n+1)(2m+1)-1 次多項式を用意して
    // 畳み込んで 2(n+1)(2m+1)-2 次多項式を得る.
    // この適切な (2n,2m) 次多項式を抜き出す.
    // 転置をとると次のようになる.
    // F を適切に配置した (2n,2m) 次多項式を作る.
    // ここから 2(n+1)(2m+1)-2 次多項式を作る.
    // これと適切な多項式の middle product をとって
    // (n+1)(2m+1)-1 次多項式を得る.
    vc<mint> A(2 * (n + 1) * (2 * m + 1) - 1);
    FOR(i, len(F)) FOR(j, len(F[0])) {
      int i1 = 2 * i + (n % 2);
      int idx = i1 * (2 * m + 1) + j;
      A[idx] = F[i][j];
    }
    vc<mint> B((n + 1) * (2 * m + 1));
    FOR(i, n + 1) FOR(j, m + 1) {
      int idx = i * (2 * m + 1) + j;
      B[idx] = G1[i][j];
    }

    A = middle_product<mint>(A, B);
    assert(len(A) == (n + 1) * (2 * m + 1));
    vv(mint, res, n + 1, m + 1);
    FOR(i, n + 1) FOR(j, m + 1) {
      int idx = (2 * m + 1) * i + j;
      res[i][j] = A[idx];
    }
    return res;
  };
  vv(mint, G, N + 1, 2);
  G[0][0] = 1;
  FOR(i, N + 1) G[i][1] = -g[i];
  vvc<mint> F = dfs(dfs, G);
  assert(degree(F) == (pair<int, int>{N, 1}));
  vc<mint> ANS(N + 1);
  FOR(i, N + 1) ANS[i] = F[i][0];
  // 最後に reverse する
  reverse(all(ANS));
  return ANS;
}

using coefficient = modint998;

} // namespace formal_power_series_composition_internal

/// @brief Compose two formal power series modulo x^n over 998244353.
/// After shifting away g(0), transposition turns composition into simultaneous
/// coefficient extraction from powers of g. A bivariate Bostan-Mori recursion
/// halves the x degree at every level; reversing that recursion applies the
/// transposed two-dimensional convolutions and reconstructs all coefficients.
inline std::vector<std::uint32_t> formal_power_series_composition_998244353(
    const std::vector<std::uint32_t> &outer,
    const std::vector<std::uint32_t> &inner) {
  assert(outer.size() == inner.size());
  using namespace formal_power_series_composition_internal;
  vc<coefficient> f(outer.begin(), outer.end());
  vc<coefficient> g(inner.begin(), inner.end());
  f = composition<coefficient>(std::move(f), std::move(g));
  std::vector<std::uint32_t> result(f.size());
  for (int i = 0; i < int(f.size()); i++) {
    result[i] = f[i].val;
  }
  return result;
}

/// @brief Invert a formal power series under composition over 998244353.
/// Lagrange inversion expresses the coefficients of the inverse through one
/// diagonal of powers of f. Bivariate Bostan-Mori extracts that diagonal in
/// O(n log^2 n); a formal (-1/n)-th power then recovers g(x)/x, followed by the
/// linear-coefficient rescaling that was normalized at the start.
inline std::vector<std::uint32_t>
formal_power_series_compositional_inverse_998244353(
    const std::vector<std::uint32_t> &series) {
  using namespace formal_power_series_composition_internal;
  vc<coefficient> f(series.begin(), series.end());
  f = compositional_inverse<coefficient>(std::move(f));
  std::vector<std::uint32_t> result(f.size());
  for (int i = 0; i < int(f.size()); i++) {
    result[i] = f[i].val;
  }
  return result;
}

} // namespace noya

#undef vv
#undef FOR1
#undef FOR2
#undef FOR3
#undef FOR4
#undef FOR1_R
#undef FOR2_R
#undef FOR3_R
#undef overload4
#undef overload3
#undef FOR
#undef FOR_R
#undef all
#undef len
#undef elif
#undef eb
#undef mp
#undef mt
#undef fi
#undef se