Problem p02539 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
#define N_MAX 200002

#define debug_value(x)                                                         \\
  cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << #x << "=" << x     \\
       << endl;
#define debug(x)                                                               \\
  cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << x << endl;

using namespace std;
typedef long long ll;

const ll MOD = 998244353;

#define root 3

unsigned int add(const unsigned int x, const unsigned int y) {
  return (x + y < MOD) ? x + y : x + y - MOD;
}

unsigned int sub(const unsigned int x, const unsigned int y) {
  return (x >= y) ? (x - y) : (MOD - y + x);
}

unsigned int mul(const unsigned int x, const unsigned int y) {
  return (unsigned long long)x * y % MOD;
}

unsigned int mod_pow(unsigned int x, unsigned int n) {
  unsigned int res = 1;
  while (n > 0) {
    if (n & 1) {
      res = mul(res, x);
    }
    x = mul(x, x);
    n >>= 1;
  }
  return res;
}

unsigned int inverse(const unsigned int x) { return mod_pow(x, MOD - 2); }

void ntt(vector<int> &a, const bool rev = false) {
  unsigned int i, j, k, l, p, q, r, s;
  const unsigned int size = a.size();
  if (size == 1)
    return;
  vector<int> b(size);
  r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
  s = mod_pow(root, r);
  vector<unsigned int> kp(size / 2 + 1, 1);
  for (i = 0; i < size / 2; ++i)
    kp[i + 1] = mul(kp[i], s);
  for (i = 1, l = size / 2; i < size; i <<= 1, l >>= 1) {
    for (j = 0, r = 0; j < l; ++j, r += i) {
      for (k = 0, s = kp[i * j]; k < i; ++k) {
        p = a[k + r], q = a[k + r + size / 2];
        b[k + 2 * r] = add(p, q);
        b[k + 2 * r + i] = mul(sub(p, q), s);
      }
    }
    swap(a, b);
  }
  if (rev) {
    s = inverse(size);
    for (i = 0; i < size; i++) {
      a[i] = mul(a[i], s);
    }
  }
}

vector<int> convolute(const vector<int> &a, const vector<int> &b) {
  const int size = (int)a.size() + (int)b.size() - 1;
  int t = 1;
  while (t < size) {
    t <<= 1;
  }
  vector<int> A(t, 0), B(t, 0);
  for (int i = 0; i < (int)a.size(); i++) {
    A[i] = a[i];
  }
  for (int i = 0; i < (int)b.size(); i++) {
    B[i] = b[i];
  }
  ntt(A), ntt(B);
  for (int i = 0; i < t; i++) {
    A[i] = mul(A[i], B[i]);
  }
  ntt(A, true);
  A.resize(size);
  return A;
}

class ModInt {
public:
  ll v;
  ModInt(ll _v = 0) { v = _v; }
  ModInt operator+(ll n) { return ModInt((v + n) % MOD); }
  ModInt operator-(ll n) { return ModInt((v - n + MOD) % MOD); }
  ModInt operator*(ll n) { return ModInt((v * n) % MOD); }
  ModInt operator/(ll n) { return ModInt((ModInt(n).inv() * v).v % MOD); }

  void operator+=(ll n) { v = (v + n) % MOD; }
  void operator-=(ll n) { v = (v - n + MOD) % MOD; }
  void operator*=(ll n) { v = (v * n) % MOD; }

  ModInt operator+(ModInt n) { return ModInt((v + n.v) % MOD); }
  ModInt operator-(ModInt n) { return ModInt((v - n.v + MOD) % MOD); }
  ModInt operator*(ModInt n) { return ModInt((v * n.v) % MOD); }
  ModInt operator/(ModInt n) { return ModInt((n.inv() * v).v % MOD); }

  void operator+=(ModInt n) { v = (v + n.v) % MOD; }
  void operator-=(ModInt n) { v = (v - n.v + MOD) % MOD; }
  void operator*=(ModInt n) { v = (v * n.v) % MOD; }

  void operator=(ModInt n) { v = n.v; }
  void operator=(ll n) { v = n; }

  ModInt inv() {
    if (v == 1)
      return ModInt(1);
    else
      return ModInt(MOD - ModInt(MOD % v).inv().v * (MOD / v) % MOD);
  }
};

ostream &operator<<(ostream &os, const ModInt &m) {
  os << m.v;
  return os;
}

istream &operator>>(istream &in, ModInt &m) {
  in >> m.v;
  return in;
}

ModInt pow(ModInt a, ll n) {
  ModInt ans = 1;
  ModInt tmp = a;
  for (int i = 0; i <= 60; i++) {
    ll m = (ll)1 << i;
    if (m & n) {
      ans *= tmp;
    }
    tmp *= tmp;
  }
  return ans;
}

ModInt inv[N_MAX], fac[N_MAX], finv[N_MAX];

void init() {
  fac[0] = 1;
  fac[1] = 1;
  finv[0] = 1;
  finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < N_MAX; i++) {
    inv[i] = (ModInt)MOD - inv[MOD % i] * (MOD / i);
    fac[i] = fac[i - 1] * (ll)i;
    finv[i] = finv[i - 1] * inv[i];
  }
}

ModInt comb(ll n, ll r) {
  if (n < r) {
    return ModInt(0);
  } else {
    return fac[n] * finv[r] * finv[n - r];
  }
}

int N;
int cnt[100005];

vector<int> calc(vector<vector<int>> v) {
  if (v.size() == 1)
    return v[0];
  if (v.size() == 2)
    return convolute(v[0], v[1]);
  int sz = v.size();
  vector<vector<int>> l, r;
  int tmp_sum = 0;
  for (int i = 0; i < sz; i++) {
    if (i * 2 > sz)
      r.push_back(v[i]);
    else
      l.push_back(v[i]);
  }
  return convolute(calc(l), calc(r));
}

// n人をm組
ModInt devide(ll n, ll m) {
  return comb(n, 2 * m) * fac[2 * m] * finv[m] / pow(2, m);
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(10) << fixed;
  cin >> N;
  for (int i = 0; i < 2 * N; i++) {
    int h;
    cin >> h;
    cnt[h]++;
  }
  init();
  vector<vector<int>> v;

  for (int i = 1; i <= 100000; i++) {
    if (cnt[i] == 0)
      continue;
    vector<int> u;
    for (int j = 0; 2 * j <= cnt[i]; j++) {
      ModInt tmp = devide(cnt[i], j);
      u.push_back(tmp.v);
    }
    v.push_back(u);
  }
  ModInt ans = 0;
  auto u = calc(v);

  for (int i = 0; 2 * i <= 2 * N && i < u.size(); i++) {
    ModInt tmp = ModInt(u[i]) * devide(2 * N - 2 * i, N - i);
    if (i % 2 == 0) {
      ans += tmp;
    } else {
      ans -= tmp;
    }
    // cout << u[i] << ':' << tmp << ' ';
  }
  // cout << endl;
  // cout << devide(4, 2) << endl;
  cout << ans << endl;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
#define N_MAX 200002

#define debug_value(x)                                                         \\
  cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << #x << "=" << x     \\
       << endl;
#define debug(x)                                                               \\
  cerr << "line" << __LINE__ << ":<" << __func__ << ">:" << x << endl;

using namespace std;
typedef long long ll;

const ll MOD = 998244353;

#define root 3

unsigned int add(const unsigned int x, const unsigned int y) {
  return (x + y < MOD) ? x + y : x + y - MOD;
}

unsigned int sub(const unsigned int x, const unsigned int y) {
  return (x >= y) ? (x - y) : (MOD - y + x);
}

unsigned int mul(const unsigned int x, const unsigned int y) {
  return (unsigned long long)x * y % MOD;
}

unsigned int mod_pow(unsigned int x, unsigned int n) {
  unsigned int res = 1;
  while (n > 0) {
    if (n & 1) {
      res = mul(res, x);
    }
    x = mul(x, x);
    n >>= 1;
  }
  return res;
}

unsigned int inverse(const unsigned int x) { return mod_pow(x, MOD - 2); }

void ntt(vector<int> &a, const bool rev = false) {
  unsigned int i, j, k, l, p, q, r, s;
  const unsigned int size = a.size();
  if (size == 1)
    return;
  vector<int> b(size);
  r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
  s = mod_pow(root, r);
  vector<unsigned int> kp(size / 2 + 1, 1);
  for (i = 0; i < size / 2; ++i)
    kp[i + 1] = mul(kp[i], s);
  for (i = 1, l = size / 2; i < size; i <<= 1, l >>= 1) {
    for (j = 0, r = 0; j < l; ++j, r += i) {
      for (k = 0, s = kp[i * j]; k < i; ++k) {
        p = a[k + r], q = a[k + r + size / 2];
        b[k + 2 * r] = add(p, q);
        b[k + 2 * r + i] = mul(sub(p, q), s);
      }
    }
    swap(a, b);
  }
  if (rev) {
    s = inverse(size);
    for (i = 0; i < size; i++) {
      a[i] = mul(a[i], s);
    }
  }
}

vector<int> convolute(const vector<int> &a, const vector<int> &b) {
  const int size = (int)a.size() + (int)b.size() - 1;
  int t = 1;
  while (t < size) {
    t <<= 1;
  }
  vector<int> A(t, 0), B(t, 0);
  for (int i = 0; i < (int)a.size(); i++) {
    A[i] = a[i];
  }
  for (int i = 0; i < (int)b.size(); i++) {
    B[i] = b[i];
  }
  ntt(A), ntt(B);
  for (int i = 0; i < t; i++) {
    A[i] = mul(A[i], B[i]);
  }
  ntt(A, true);
  A.resize(size);
  return A;
}

class ModInt {
public:
  ll v;
  ModInt(ll _v = 0) { v = _v; }
  ModInt operator+(ll n) { return ModInt((v + n) % MOD); }
  ModInt operator-(ll n) { return ModInt((v - n + MOD) % MOD); }
  ModInt operator*(ll n) { return ModInt((v * n) % MOD); }
  ModInt operator/(ll n) { return ModInt((ModInt(n).inv() * v).v % MOD); }

  void operator+=(ll n) { v = (v + n) % MOD; }
  void operator-=(ll n) { v = (v - n + MOD) % MOD; }
  void operator*=(ll n) { v = (v * n) % MOD; }

  ModInt operator+(ModInt n) { return ModInt((v + n.v) % MOD); }
  ModInt operator-(ModInt n) { return ModInt((v - n.v + MOD) % MOD); }
  ModInt operator*(ModInt n) { return ModInt((v * n.v) % MOD); }
  ModInt operator/(ModInt n) { return ModInt((n.inv() * v).v % MOD); }

  void operator+=(ModInt n) { v = (v + n.v) % MOD; }
  void operator-=(ModInt n) { v = (v - n.v + MOD) % MOD; }
  void operator*=(ModInt n) { v = (v * n.v) % MOD; }

  void operator=(ModInt n) { v = n.v; }
  void operator=(ll n) { v = n; }

  ModInt inv() {
    if (v == 1)
      return ModInt(1);
    else
      return ModInt(MOD - ModInt(MOD % v).inv().v * (MOD / v) % MOD);
  }
};

ostream &operator<<(ostream &os, const ModInt &m) {
  os << m.v;
  return os;
}

istream &operator>>(istream &in, ModInt &m) {
  in >> m.v;
  return in;
}

ModInt pow(ModInt a, ll n) {
  ModInt ans = 1;
  ModInt tmp = a;
  for (int i = 0; i <= 60; i++) {
    ll m = (ll)1 << i;
    if (m & n) {
      ans *= tmp;
    }
    tmp *= tmp;
  }
  return ans;
}

ModInt inv[N_MAX], fac[N_MAX], finv[N_MAX];

void init() {
  fac[0] = 1;
  fac[1] = 1;
  finv[0] = 1;
  finv[1] = 1;
  inv[1] = 1;
  for (int i = 2; i < N_MAX; i++) {
    inv[i] = (ModInt)MOD - inv[MOD % i] * (MOD / i);
    fac[i] = fac[i - 1] * (ll)i;
    finv[i] = finv[i - 1] * inv[i];
  }
}

ModInt comb(ll n, ll r) {
  if (n < r) {
    return ModInt(0);
  } else {
    return fac[n] * finv[r] * finv[n - r];
  }
}

int N;
int cnt[100005];

vector<int> calc(vector<vector<int>> v) {
  if (v.size() == 1)
    return v[0];
  if (v.size() == 2)
    return convolute(v[0], v[1]);
  int sum_sz = 0;
  for (auto u : v)
    sum_sz += u.size();
  vector<vector<int>> l, r;
  int tmp_sum = 0;
  for (auto u : v) {
    tmp_sum += u.size();
    if (tmp_sum * 2 > sum_sz)
      r.push_back(u);
    else
      l.push_back(u);
  }
  return convolute(calc(l), calc(r));
}

// n人をm組
ModInt devide(ll n, ll m) {
  return comb(n, 2 * m) * fac[2 * m] * finv[m] / pow(2, m);
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(10) << fixed;
  cin >> N;
  for (int i = 0; i < 2 * N; i++) {
    int h;
    cin >> h;
    cnt[h]++;
  }
  init();
  vector<vector<int>> v;

  for (int i = 1; i <= 100000; i++) {
    if (cnt[i] == 0)
      continue;
    vector<int> u;
    for (int j = 0; 2 * j <= cnt[i]; j++) {
      ModInt tmp = devide(cnt[i], j);
      u.push_back(tmp.v);
    }
    v.push_back(u);
  }
  ModInt ans = 0;
  auto u = calc(v);

  for (int i = 0; 2 * i <= 2 * N && i < u.size(); i++) {
    ModInt tmp = ModInt(u[i]) * devide(2 * N - 2 * i, N - i);
    if (i % 2 == 0) {
      ans += tmp;
    } else {
      ans -= tmp;
    }
    // cout << u[i] << ':' << tmp << ' ';
  }
  // cout << endl;
  // cout << devide(4, 2) << endl;
  cout << ans << endl;
}