QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#67532#433. 抽卡alpha1022100 ✓721ms27960kbC++2322.0kb2022-12-10 17:02:062022-12-10 17:02:08

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-12-10 17:02:08]
  • 评测
  • 测评结果:100
  • 用时:721ms
  • 内存:27960kb
  • [2022-12-10 17:02:06]
  • 提交

answer

#include <queue>
#include <cstdio>
#include <chrono>
#include <random>
#include <vector>
#include <cstring>
#include <utility>
#include <algorithm>
#include <functional>
#include <initializer_list>

using ll = long long;

using namespace std;

const int mod = 998244353, G = 3;
inline int norm(int x) {
  return x >= mod ? x - mod : x;
}
inline int reduce(int x) {
  return x < 0 ? x + mod : x;
}
inline int neg(int x) {
  return x ? mod - x : 0;
}
inline void add(int &x, int y) {
  if ((x += y - mod) < 0)
    x += mod;
}
inline void sub(int &x, int y) {
  if ((x -= y) < 0)
    x += mod;
}
inline void fam(int &x, int y, int z) {
  x = (x + (ll)y * z) % mod;
}
inline int mpow(int a, int b) {
  int ret = 1;
  for (; b; b >>= 1)
    (b & 1) && (ret = (ll)ret * a % mod),
    a = (ll)a * a % mod;
  return ret;
}

const int BRUTE_N2_LIMIT = 50;

struct NumberTheory {
  typedef pair<int, int> P2_Field;
  mt19937 rng;
  NumberTheory(): rng(chrono::steady_clock::now().time_since_epoch().count()) {}
  void exGcd(int a, int b, int &x, int &y) {
    if (!b) {
      x = 1, y = 0;
      return;
    }
    exGcd(b, a % b, y, x), y -= a / b * x;
  }
  int inv(int a, int p = mod) {
    int x, y;
    exGcd(a, p, x, y);
    if (x < 0)
      x += p;
    return x;
  }
  template<class Integer>
  bool quadRes(Integer a, Integer b) {
    if (a <= 1)
      return 1;
    while (a % 4 == 0)
      a /= 4;
    if (a % 2 == 0)
      return (b % 8 == 1 || b % 8 == 7) == quadRes(a / 2, b);
    return ((a - 1) % 4 == 0 || (b - 1) % 4 == 0) == quadRes(b % a, a);
  }
  int sqrt(int x, int p = mod) {
    if (p == 2 || x <= 1)
      return x;
    int w, v, k = (p + 1) / 2;
    do
      w = rng() % p;
    while (quadRes(v = ((ll)w * w - x + p) % p, p));
    P2_Field res(1, 0), a(w, 1);
    for (; k; k >>= 1) {
      if (k & 1)
        res = P2_Field(((ll)res.first * a.first + (ll)res.second * a.second % p * v) % p, ((ll)res.first * a.second + (ll)res.second * a.first) % p);
      a = P2_Field(((ll)a.first * a.first + (ll)a.second * a.second % p * v) % p, 2LL * a.first * a.second % p);
    }
    return min(res.first, p - res.first);
  }
} nt;

namespace Simple {
  int n = 1;
  vector<int> fac({1, 1}), ifac({1, 1}), inv({0, 1});
  void build(int m) {
    n = m;
    fac.resize(n + 1), ifac.resize(n + 1), inv.resize(n + 1);
    inv[1] = 1;
    for (int i = 2; i <= n; ++i)
      inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod;
    fac[0] = ifac[0] = 1;
    for (int i = 1; i <= n; ++i)
      fac[i] = (ll)fac[i - 1] * i % mod,
      ifac[i] = (ll)ifac[i - 1] * inv[i] % mod;
  }
  void check(int k) {
    int m = n;
    if (k > m) {
      while (k > m)
        m <<= 1;
      build(m);
    }
  }
  inline int gfac(int k) {
    check(k);
    return fac[k];
  }
  inline int gifac(int k) {
    check(k);
    return ifac[k];
  }
  inline int ginv(int k) {
    check(k);
    return inv[k];
  }
}

struct SimpleSequence {
  function<int(int)> func;
  inline SimpleSequence(const function<int(int)> &func): func(func) {}
  inline int operator[](int k) const {
    return func(k);
  }
} gfac(Simple::gfac), gifac(Simple::gifac), ginv(Simple::ginv);

inline int binom(int n, int m) {
  if (m > n || m < 0)
    return 0;
  return (ll)gfac[n] * gifac[m] % mod * gifac[n - m] % mod;
}

namespace NTT {
  int L = -1;
  vector<int> root;
  void init(int l) {
    L = l;
    root.resize((1 << L) + 1);
    int n = 1 << L, *w = root.data();
    w[0] = 1, w[1 << L] = mpow(31, 1 << (21 - L));
    for (int i = L; i; --i)
      w[1 << (i - 1)] = (ll)w[1 << i] * w[1 << i] % mod;
    for (int i = 1; i < n; ++i)
      w[i] = (ll)w[i & (i - 1)] * w[i & -i] % mod;
  }
  void DIF(int *a, int l) {
    int n = 1 << l;
    for (int len = n >> 1; len; len >>= 1)
      for (int *j = a, *o = root.data(); j != a + n; j += len << 1, ++o)
        for (int *k = j; k != j + len; ++k) {
          int r = (ll)*o * k[len] % mod;
          k[len] = reduce(*k - r), add(*k, r);
        }
  }
  void DIT(int *a, int l) {
    int n = 1 << l;
    for (int len = 1; len < n; len <<= 1)
      for (int *j = a, *o = root.data(); j != a + n; j += len << 1, ++o)
        for (int *k = j; k != j + len; ++k) {
          int r = norm(*k + k[len]);
          k[len] = (ll)*o * (*k - k[len] + mod) % mod, *k = r;
        }
  }
  void fft(int *a, int lgn, int d = 1) {
    if (L < lgn)
      init(lgn);
    int n = 1 << lgn;
    if (d == 1)
      DIF(a, lgn);
    else {
      DIT(a, lgn), reverse(a + 1, a + n);
      int nInv = mod - (mod - 1) / n;
      for (int i = 0; i < n; ++i)
        a[i] = (ll)a[i] * nInv % mod;
    }
  }
}

struct poly {
  vector<int> a;
  poly(ll v = 0): a(1) {
    if ((v %= mod) < 0)
      v += mod;
    a[0] = v;
  }
  poly(const poly &o): a(o.a) {}
  poly(const vector<int> &o): a(o) {}
  poly(initializer_list<int> o): a(o) {}
  int operator[](int k) const { return k < a.size() ? a[k] : 0; }
  int &operator[](int k) {
    if (k >= a.size())
      a.resize(k + 1);
    return a[k];
  }
  int deg() const { return (int)a.size() - 1; }
  void redeg(int d) { a.resize(d + 1); }
  int size() const {return a.size(); }
  void resize(int s) { a.resize(s); }
  poly slice(int d) const {
    if (d < a.size())
      return vector<int>(a.begin(), a.begin() + d + 1);
    vector<int> ret = a;
    ret.resize(d + 1);
    return ret;
  }
  poly shift(int k) const {
    if (size() + k <= 0)
      return 0;
    vector<int> ret(size() + k);
    for (int i = max(0, k); i < ret.size(); ++i)
      ret[i] = a[i - k];
    return ret;
  }
  int *base() { return a.data(); }
  const int *base() const { return a.data(); }
  poly println(FILE *fp = stdout) const {
    for (int i = 0; i < a.size(); ++i)
      fprintf(fp, "%d%c", a[i], " \n"[i == a.size() - 1]);
    return *this;
  }

  poly &operator+=(const poly &o) {
    if (o.size() > a.size())
      a.resize(o.size());
    for (int i = 0; i < o.size(); ++i)
      add(a[i], o[i]);
    return *this;
  }
  poly operator+(const poly &o) const { poly ret(a); ret += o; return ret; }
  poly operator-() const {
    poly ret = a;
    for (int i = 0; i < a.size(); ++i)
      ret[i] = neg(ret[i]);
    return ret;
  }
  poly &operator-=(const poly &o) { return operator+=(-o); }
  poly operator-(const poly &o) { return operator+(-o); }
  poly operator*(const poly &) const;
  poly operator/(const poly &) const;
  poly operator%(const poly &) const;
  poly &operator*=(const poly &o) { *this = operator*(o); return *this; }
  poly &operator/=(const poly &o) { *this = operator/(o); return *this; }
  poly &operator%=(const poly &o) { *this = operator%(o); return *this; }
  poly deriv() const;
  poly integ() const;
  poly inv() const;
  poly sqrt() const;
  poly ln() const;
  poly exp() const;
  poly srcExp() const;
  pair<poly, poly> sqrti() const;
  pair<poly, poly> expi() const;
  poly quo(const poly &) const;
  pair<poly, poly> iquo() const;
  pair<poly, poly> div(const poly &) const;
  poly taylor(int k) const;
  poly pow(int k) const;
  poly exp(int k) const;
};

poly zeroes(int d) { return vector<int>(d + 1); }

namespace NTT { void fft(poly &a, int lgn, int d = 1) { fft(a.base(), lgn, d); } }

using NTT::fft;

struct Newton {
  void inv(const poly &f, const poly &dftf, poly &g, const poly &dftg, int t) {
    int n = 1 << t;
    poly prod = dftf;
    for (int i = 0; i < (n << 1); ++i)
      prod[i] = (ll)prod[i] * dftg[i] % mod;
    fft(prod, t + 1, -1);
    memset(prod.base(), 0, sizeof(int) << t);
    fft(prod, t + 1);
    for (int i = 0; i < (n << 1); ++i)
      prod[i] = (ll)prod[i] * dftg[i] % mod;
    fft(prod, t + 1, -1);
    for (int i = 0; i < n; ++i)
      prod[i] = 0;
    g -= prod;
  }
  void inv(const poly &f, const poly &dftf, poly &g, int t) {
    poly dftg(g);
    dftg.resize(2 << t);
    fft(dftg, t + 1);
    inv(f, dftf, g, dftg, t);
  }
  void inv(const poly &f, poly &g, int t) {
    poly dftf(f), dftg(g);
    dftf.resize(2 << t), dftg.resize(2 << t);
    fft(dftf, t + 1), fft(dftg, t + 1);
    inv(f, dftf, g, dftg, t);
  }
  void sqrt(const poly &f, poly &g, poly &dftg, poly &h, int t) {
    for (int i = 0; i < (1 << t); ++i)
      dftg[i] = (ll)dftg[i] * dftg[i] % mod;
    fft(dftg, t, -1);
    dftg -= f;
    for (int i = 0; i < (1 << t); ++i)
      add(dftg[i | (1 << t)], dftg[i]),
      dftg[i] = 0;
    fft(dftg, t + 1);
    poly tmp = h;
    tmp.resize(2 << t);
    fft(tmp, t + 1);
    for (int i = 0; i < (2 << t); ++i)
      tmp[i] = (ll)tmp[i] * dftg[i] % mod;
    fft(tmp, t + 1, -1);
    memset(tmp.base(), 0, sizeof(int) << t);
    g -= tmp * ginv[2];
  }
  void exp(const poly &f, poly &g, poly &dftg, poly &h, int t) {
    poly dfth = h;
    fft(dfth, t);
    poly dg = g.deriv().slice((1 << t) - 1);
    fft(dg, t);
    poly tmp = zeroes((1 << t) - 1);
    for (int i = 0; i < (1 << t); ++i)
      tmp[i] = (ll)dftg[i] * dfth[i] % mod,
      dg[i] = (ll)dg[i] * dfth[i] % mod;
    fft(tmp, t, -1), fft(dg, t, -1);
    sub(tmp[0], 1);
    dg.resize(2 << t);
    poly df0 = f.deriv().slice((1 << t) - 1);
    df0[(1 << t) - 1] = 0;
    for (int i = 0; i < (1 << t); ++i)
      dg[i | (1 << t)] = reduce(dg[i] - df0[i]);
    memcpy(dg.base(), df0.base(), sizeof(int) * ((1 << t) - 1));
    tmp.resize(2 << t), fft(tmp, t + 1);
    df0.resize(2 << t), fft(df0, t + 1);
    for (int i = 0; i < (2 << t); ++i)
      df0[i] = (ll)df0[i] * tmp[i] % mod;
    fft(df0, t + 1, -1);
    for (int i = 0; i < (1 << t); ++i)
      df0[i | (1 << t)] = df0[i],
      df0[i] = 0;
    dg = (dg - df0).integ().slice((2 << t) - 1) - f;
    fft(dg, t + 1);
    for (int i = 0; i < (2 << t); ++i)
      tmp[i] = (ll)dg[i] * dftg[i] % mod;
    fft(tmp, t + 1, -1);
    g.resize(2 << t);
    for (int i = 1 << t; i < (2 << t); ++i)
      g[i] = neg(tmp[i]);
  }
} nit;

poly poly::operator*(const poly &o) const {
  int n = deg(), m = o.deg();
  if (n <= 10 || m <= 10 || n + m <= BRUTE_N2_LIMIT) {
    poly ret = zeroes(n + m);
    for (int i = 0; i <= n; ++i)
      for (int j = 0; j <= m; ++j)
        fam(ret[i + j], a[i], o[j]);
    return ret;
  }
  n += m;
  int l = 0;
  while ((1 << l) <= n)
    ++l;
  poly ret = a, tmp = o;
  ret.resize(1 << l), tmp.resize(1 << l);
  fft(ret, l), fft(tmp, l);
  for (int i = 0; i < (1 << l); ++i)
    ret[i] = (ll)ret[i] * tmp[i] % mod;
  fft(ret, l, -1);
  return ret.slice(n);
}
poly poly::inv() const {
  poly g = nt.inv(a[0]);
  for (int t = 0; (1 << t) <= deg(); ++t)
    nit.inv(slice((2 << t) - 1), g, t);
  g.redeg(deg());
  return g;
}
poly poly::taylor(int k) const {
  int n = deg();
  poly f = zeroes(n), g = zeroes(n);
  for (int i = 0, pw = 1; i <= n; ++i)
    f[n - i] = (ll)a[i] * gfac[i] % mod,
    g[i] = (ll)pw * gifac[i] % mod,
    pw = (ll)pw * k % mod;
  f *= g;
  for (int i = 0; i <= n; ++i)
    g[i] = (ll)f[n - i] * gifac[i] % mod;
  return g;
}
poly poly::pow(int k) const {
  if (k == 0)
    return 1;
  if (k == 1)
    return *this;
  int n = deg() * k;
  int l = 0;
  while ((1 << l) <= n)
    ++l;
  poly ret = a;
  ret.resize(1 << l), fft(ret, l);
  for (int i = 0; i < (1 << l); ++i)
    ret[i] = mpow(ret[i], k);
  fft(ret, -1);
  return ret.slice(n);
}
poly poly::deriv() const {
  if (deg() == 0)
    return 0;
  vector<int> ret(deg());
  for (int i = 0; i < deg(); ++i)
    ret[i] = (ll)a[i + 1] * (i + 1) % mod;
  return ret;
}
poly poly::integ() const {
  vector<int> ret(size() + 1);
  for (int i = 0; i <= deg(); ++i)
    ret[i + 1] = (ll)a[i] * ginv[i + 1] % mod;
  return ret;
}
poly poly::quo(const poly &o) const {
  if (o.deg() == 0)
    return (ll)a[0] * nt.inv(o[0]) % mod;
  poly g = nt.inv(o[0]);
  int t = 0, n;
  for (n = 1; (n << 1) <= o.deg(); ++t, n <<= 1)
    nit.inv(o.slice((n << 1) - 1), g, t);
  poly dftg = g;
  dftg.resize(n << 1), fft(dftg, t + 1);
  poly eps1 = o;
  eps1.resize(n << 1), fft(eps1, t + 1);
  for (int i = 0; i < (n << 1); ++i)
    eps1[i] = (ll)eps1[i] * dftg[i] % mod;;
  fft(eps1, t + 1, -1);
  for (int i = 0; i < n; ++i)
    eps1[i] = eps1[i + n],
    eps1[i + n] = 0;
  fft(eps1, t + 1);
  poly h0 = slice(n - 1);
  h0.resize(n << 1), fft(h0, t + 1);
  poly h0g0 = zeroes((n << 1) - 1);
  for (int i = 0; i < (n << 1); ++i)
    h0g0[i] = (ll)h0[i] * dftg[i] % mod;
  fft(h0g0, t + 1, -1);
  poly h0eps1 = zeroes((n << 1) - 1);
  for (int i = 0; i < (n << 1); ++i)
    h0eps1[i] = (ll)h0[i] * eps1[i] % mod;
  fft(h0eps1, t + 1, -1);
  for (int i = 0; i < n; ++i)
    h0eps1[i] = reduce(operator[](i + n) - h0eps1[i]);
  memset(h0eps1.base() + n, 0, sizeof(int) << t);
  fft(h0eps1, t + 1);
  for (int i = 0; i < (n << 1); ++i)
    h0eps1[i] = (ll)h0eps1[i] * dftg[i] % mod;
  fft(h0eps1, t + 1, -1);
  for (int i = 0; i < n; ++i)
    h0eps1[i + n] = h0eps1[i],
    h0eps1[i] = 0;
  return (h0g0 + h0eps1).slice(o.deg());
}
poly poly::ln() const {
  if (deg() == 0)
    return 0;
  return deriv().quo(slice(deg() - 1)).integ();
}
pair<poly, poly> poly::sqrti() const {
  poly g = nt.sqrt(a[0]), h = nt.inv(a[0]), dftg = g;
  for (int t = 0; (1 << t) <= deg(); ++t) {
    nit.sqrt(slice((2 << t) - 1), g, dftg, h, t);
    dftg = g, fft(dftg, t + 1);
    nit.inv(g, dftg, h, t);
  }
  return make_pair(g.slice(deg()), h.slice(deg()));
}
poly poly::sqrt() const {
  poly g = nt.sqrt(a[0]), h = nt.inv(a[0]), dftg = g;
  for (int t = 0; (1 << t) <= deg(); ++t) {
    nit.sqrt(slice((2 << t) - 1), g, dftg, h, t);
    if ((2 << t) <= deg()) {
      dftg = g, fft(dftg, t + 1);
      nit.inv(g, dftg, h, t);
    }
  }
  return g.slice(deg());
}
pair<poly, poly> poly::expi() const {
  poly g = 1, h = 1, dftg = {1, 1};
  for (int t = 0; (1 << t) <= deg(); ++t) {
    nit.exp(slice((2 << t) - 1), g, dftg, h, t);
    dftg = g, dftg.resize(4 << t);
    fft(dftg, t + 2);
    poly f2n = dftg.slice((2 << t) - 1);
    nit.inv(g, f2n, h, t);
  }
  return make_pair(g.slice(deg()), h.slice(deg()));
}
poly poly::exp() const {
  poly g = 1, h = 1, dftg = {1, 1};
  for (int t = 0; (1 << t) <= deg(); ++t) {
    nit.exp(slice((2 << t) - 1), g, dftg, h, t);
    if ((2 << t) <= deg()) {
      dftg = g, dftg.resize(4 << t);
      fft(dftg, t + 2);
      poly f2n = dftg.slice((2 << t) - 1);
      nit.inv(g, f2n, h, t);
    }
  }
  return g.slice(deg());
}
poly poly::exp(int k) const {
  int lead, lz = 0;
  while (lz < deg() && !a[lz])
    ++lz;
  if (lz == deg() && !a[lz])
    return *this;
  lead = a[lz];
  if ((ll)lz * k > deg())
    return zeroes(deg());
  poly part = poly(vector<int>(a.begin() + lz, a.begin() + deg() - lz * (k - 1) + 1)) * nt.inv(lead);
  part = (part.ln() * k).exp() * mpow(lead, k);
  vector<int> ret(deg() + 1);
  memcpy(ret.data() + lz * k, part.base(), sizeof(int) * (deg() - lz * k + 1));
  return ret;
}
poly poly::operator/(const poly &o) const {
  int n = deg(), m = o.deg();
  if (n < m)
    return 0;
  poly ta(vector<int>(a.rbegin(), a.rend())), tb(vector<int>(o.a.rbegin(), o.a.rend()));
  ta.redeg(n - m), tb.redeg(n - m);
  poly q = ta.quo(tb);
  return vector<int>(q.a.rbegin(), q.a.rend());
}
pair<poly, poly> poly::div(const poly &o) const {
  if (deg() < o.deg())
    return make_pair(0, *this);
  int n = deg(), m = o.deg();
  poly q = operator/(o), r;
  int l = 0;
  while ((1 << l) < o.deg())
    ++l;
  int t = (1 << l) - 1;
  poly tmp = zeroes(t);
  r = zeroes(t);
  for (int i = 0; i <= m; ++i)
    add(r[i & t], o[i]);
  for (int i = 0; i <= n - m; ++i)
    add(tmp[i & t], q[i]);
  fft(r, l), fft(tmp, l);
  for (int i = 0; i <= t; ++i)
    tmp[i] = (ll)tmp[i] * r[i] % mod;
  fft(tmp, l, -1);
  memset(r.base(), 0, sizeof(int) << l);
  for (int i = 0; i <= n; ++i)
    add(r[i & t], a[i]);
  for (int i = 0; i < m; ++i)
    sub(r[i], tmp[i]);
  return make_pair(q, r.slice(m - 1));
}
poly poly::operator%(const poly &o) const {
  return div(o).second;
}

struct RelaxedConvolution {
  static const int LG = 19;
  static const int B = 16;
  void run(const int *f, int *g, const int *df, const int *dg, int t, int n, const function<void(int)> &relax) {
    vector<vector<int>> savef(LG + 1), saveg(LG + 1), savedf(LG + 1), savedg(LG + 1);
    function<void(int, int)> divideConquer = [&](int l, int r) {
      if (r - l <= BRUTE_N2_LIMIT) {
        for (int i = l + 1; i <= r; ++i) {
          for (int j = l; j < i; ++j)
            fam(g[i], df[j], g[i - j]),
            fam(g[i], dg[j], f[i - j]);
          if (l > 0)
            for (int j = l; j < i; ++j)
              fam(g[i], g[j], df[i - j]),
              fam(g[i], f[j], dg[i - j]);
          relax(i);
        }
        return ;
      }
      if (l == 0) {
        int mid = ((l + r) >> 1) + 5;
        divideConquer(l, mid);
        int lgd = 0;
        while ((1 << lgd) <= r)
          ++lgd;
        vector<int> tf(1 << lgd), tg(1 << lgd), tdf(1 << lgd), tdg(1 << lgd);
        for (int i = 0; i < mid; ++i)
          tf[i] = f[i], tg[i] = g[i],
          tdf[i] = df[i], tdg[i] = dg[i];
        fft(tf.data(), lgd), fft(tg.data(), lgd),
        fft(tdf.data(), lgd), fft(tdg.data(), lgd);
        for (int i = 0; i < (1 << lgd); ++i)
          tdf[i] = (ll)tdf[i] * tg[i] % mod,
          tdg[i] = (ll)tdg[i] * tf[i] % mod;
        fft(tdf.data(), lgd, -1), fft(tdg.data(), lgd, -1);
        for (int i = mid + 1; i <= r; ++i)
          add(g[i], norm(tdf[i] + tdg[i]));
        divideConquer(mid, r);
        return ;
      }
      int d = (r - l) / B + 1, lgd = 0, lg;
      while ((1 << lgd) <= d * 2)
        ++lgd;
      d = (1 << (lgd - 1)) - 1, lg = (r - l + d - 1) / d;

      vector<int> dftf = savef[lgd], dftg = saveg[lgd],
                  dftdf = savedf[lgd], dftdg = savedg[lgd];
      dftf.resize(lg << (lgd + 1)), dftg.resize(lg << (lgd + 1)),
      dftdf.resize(lg << (lgd + 1)), dftdg.resize(lg << (lgd + 1));
      for (int i = lg << lgd; i < (lg << (lgd + 1)); ++i)
        dftf[i] = dftg[i] = dftdf[i] = dftdg[i] = 0;
      int ef = lg;
      for (int i = 0; i < lg; ++i) {
        if ((i << lgd) < savef[lgd].size())
          continue;
        if ((i + 2) * d >= l)
          --ef;
        for (int j = 0; j <= d * 2; ++j)
          dftf[(i << lgd) + j] = f[i * d + j],
          dftg[(i << lgd) + j] = g[i * d + j],
          dftdf[(i << lgd) + j] = df[i * d + j],
          dftdg[(i << lgd) + j] = dg[i * d + j];
        fft(dftf.data() + (i << lgd), lgd), fft(dftg.data() + (i << lgd), lgd),
        fft(dftdf.data() + (i << lgd), lgd), fft(dftdg.data() + (i << lgd), lgd);
      }
      if (savef[lgd].size() < (ef << lgd))
        savef[lgd] = vector<int>(dftf.begin(), dftf.begin() + (ef << lgd)),
        saveg[lgd] = vector<int>(dftg.begin(), dftg.begin() + (ef << lgd)),
        savedf[lgd] = vector<int>(dftdf.begin(), dftdf.begin() + (ef << lgd)),
        savedg[lgd] = vector<int>(dftdg.begin(), dftdg.begin() + (ef << lgd));
      for (int i = 0; i < lg; ++i) {
        if (i) {
          for (int j = 0; j < (1 << lgd); ++j)
            dftg[((lg + i) << lgd) + j] = norm(dftdf[((lg + i) << lgd) + j] + dftdg[((lg + i) << lgd) + j]);
          fft(dftg.data() + ((lg + i) << lgd), lgd, -1);
        }
        for (int j = 1; j <= min(d, r - l - i * d); ++j)
          add(g[l + i * d + j], dftg[((lg + i) << lgd) + d + j]);
        divideConquer(l + i * d, min(l + (i + 1) * d, r));
        if (i + 1 < lg) {
          for (int j = 0; j < d; ++j)
            dftf[((lg + i) << lgd) + j] = f[l + i * d + j],
            dftg[((lg + i) << lgd) + j] = g[l + i * d + j],
            dftdf[((lg + i) << lgd) + j] = df[l + i * d + j],
            dftdg[((lg + i) << lgd) + j] = dg[l + i * d + j];
          for (int j = d; j < (1 << lgd); ++j)
            dftg[((lg + i) << lgd) + j] = dftdf[((lg + i) << lgd) + j] = dftdg[((lg + i) << lgd) + j] = 0;
          fft(dftf.data() + ((lg + i) << lgd), lgd), fft(dftg.data() + ((lg + i) << lgd), lgd),
          fft(dftdf.data() + ((lg + i) << lgd), lgd), fft(dftdg.data() + ((lg + i) << lgd), lgd);
        }
        for (int j = i + 1; j < lg; ++j)
          for (int k = 0; k < (1 << lgd); ++k)
            fam(dftdf[((lg + j) << lgd) + k], dftdf[((j - i - 1) << lgd) + k], dftg[((lg + i) << lgd) + k]),
            fam(dftdf[((lg + j) << lgd) + k], dftg[((j - i - 1) << lgd) + k], dftdf[((lg + i) << lgd) + k]),
            fam(dftdg[((lg + j) << lgd) + k], dftdg[((j - i - 1) << lgd) + k], dftf[((lg + i) << lgd) + k]),
            fam(dftdg[((lg + j) << lgd) + k], dftf[((j - i - 1) << lgd) + k], dftdg[((lg + i) << lgd) + k]);
      }
    };
    relax(0), divideConquer(0, n);
  }
} rc;

const int N = 2e5 + 1;

int m, k, t;

poly f;
int g[N + 5], df[N + 5], dg[N + 5];

int a[N + 5];
vector<int> lens;
vector<poly> seq;
poly solve(int l, int r) {
  if (l == r)
    return seq[l];
  int mid = (l + r) >> 1;
  return solve(l, mid) * solve(mid + 1, r);
}

int ans;

int main() {
  scanf("%d%d", &m, &k), t = k + 1;
  f.redeg(m + 1), rc.run(f.base(), g, df, dg, t, m + 1, [&](int k) {
    if (k < t) g[k] = 0;
    else if (k == t) g[k] = 1;
    else g[k] = (ll)ginv[k - t] * g[k] % mod;
    if (k == 0) f[k] = 0;
    else if (k == 1) f[k] = 1;
    else f[k] = reduce(g[k] - f[k - 1]);
    if (k > 0)
      df[k - 1] = (ll)k * f[k] % mod * t % mod,
      dg[k - 1] = (ll)(mod - k) * g[k] % mod;
  });
  f = f.shift(-1).inv();
  for (int i = 1; i <= m; ++i)
    scanf("%d", a + i);
  sort(a + 1, a + m + 1), a[0] = -1;
  for (int i = 1; i <= m; ++i)
    if (a[i - 1] + 1 == a[i])
      ++lens.back();
    else
      lens.emplace_back(1);
  for (int len: lens) {
    poly pwr = f.slice(len).exp(len + 1), res = zeroes(len);
    for (int i = 0; i <= len; ++i)
      res[len - i] = (ll)ginv[len + 1] * (i + 1) % mod * pwr[len - i] % mod;
    seq.emplace_back(res);
  }
  poly res = solve(0, seq.size() - 1);
  for (int i = 0; i < m; ++i)
    ans = (ans + (ll)ginv[m - i] * nt.inv(binom(m, i)) % mod * res[i]) % mod;
  ans = (ll)ans * m % mod;
  printf("%d\n", ans);
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 10
Accepted
time: 1ms
memory: 3164kb

input:

10 3
1 2 3 5 6 7 8 9 10 11

output:

23767731

result:

ok 1 number(s): "23767731"

Test #2:

score: 10
Accepted
time: 3ms
memory: 3276kb

input:

500 499
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 10...

output:

137319993

result:

ok 1 number(s): "137319993"

Test #3:

score: 10
Accepted
time: 3ms
memory: 3156kb

input:

500 13
397 284 276 435 348 557 14 561 516 352 125 56 240 337 417 37 2 281 414 307 210 336 232 382 224 122 58 133 137 393 488 92 469 238 48 453 241 533 492 424 260 213 487 571 33 178 97 158 135 575 292 331 478 118 121 11 85 552 460 219 415 272 293 479 481 304 254 55 212 351 230 164 472 422 7 28 19 39...

output:

93022584

result:

ok 1 number(s): "93022584"

Test #4:

score: 10
Accepted
time: 3ms
memory: 3284kb

input:

500 9
464 333 321 508 405 641 14 645 599 412 147 69 279 394 488 40 2 328 486 359 243 393 270 444 261 145 71 158 162 458 568 111 547 278 59 529 280 617 571 496 302 247 567 658 35 209 115 183 160 665 343 386 556 139 144 11 103 637 539 254 487 318 344 557 558 356 293 68 246 408 268 189 549 494 7 30 20 ...

output:

508272560

result:

ok 1 number(s): "508272560"

Test #5:

score: 10
Accepted
time: 3ms
memory: 3356kb

input:

500 30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 ...

output:

730181983

result:

ok 1 number(s): "730181983"

Test #6:

score: 10
Accepted
time: 13ms
memory: 3848kb

input:

5000 100
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100...

output:

979829264

result:

ok 1 number(s): "979829264"

Test #7:

score: 10
Accepted
time: 9ms
memory: 3632kb

input:

5000 300
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100...

output:

369651884

result:

ok 1 number(s): "369651884"

Test #8:

score: 10
Accepted
time: 656ms
memory: 27888kb

input:

200000 5
1 2 3 4 5 6 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 ...

output:

297583105

result:

ok 1 number(s): "297583105"

Test #9:

score: 10
Accepted
time: 662ms
memory: 27720kb

input:

200000 2000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 ...

output:

645299783

result:

ok 1 number(s): "645299783"

Test #10:

score: 10
Accepted
time: 721ms
memory: 27960kb

input:

200000 50
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 69 70 71 72 73 74 75 76 77 78 79 80 81 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 ...

output:

66899726

result:

ok 1 number(s): "66899726"

Extra Test:

score: 0
Extra Test Passed