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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10, M = 1e5 + 10, mod = 998244353, G = 3;

int n;
int a[N], b[N], fac[N], finv[N], two[N];

ll A[N], B[N], inv, tong[M];
int R[N];
int power(int x, int n) {
  int res = 1;
  for (; n; n >>= 1, x = 1ll * x * x % mod)
    if (n & 1)
      res = 1ll * res * x % mod;
  return res;
}
vector<int> colors[N << 1];
struct cmp {
  bool operator()(int a, int b) { return colors[a].size() > colors[b].size(); }
};
priority_queue<int, vector<int>, cmp> heap;
void NTT(ll a[], int n, int re) {
  for (int i = 0; i < n; i++)
    if (i < R[i])
      swap(a[i], a[R[i]]);
  for (int i = 2; i <= n; i <<= 1) {
    ll mid = i >> 1;
    ll wn = power(G, (mod - 1) / i);
    if (re)
      wn = power(wn, (mod - 2));
    for (int j = 0; j < n; j += i) {
      ll w = 1;
      for (int k = 0; k < mid; k++) {
        ll temp1 = a[j + k];
        ll temp2 = a[j + k + mid] * w % mod;
        a[j + k] = (temp1 + temp2) % mod;
        a[j + k + mid] = (temp1 - temp2);
        a[j + k + mid] = (a[j + k + mid] % mod + mod) % mod;
        w = w * wn % mod;
      }
    }
  }
  if (re) {
    for (int i = 0; i < n; i++)
      a[i] = (a[i] * inv) % mod;
  }
}
void NTT_times(vector<int> &a, vector<int> &b, vector<int> &c) {
  int n, d, as = a.size(), bs = b.size();
  for (int i = 0; i < as; i++)
    A[i] = a[i];
  for (int i = 0; i < bs; i++)
    B[i] = b[i];
  for (n = 1, d = 0; n < as + bs - 1; n <<= 1, d++)
    ;
  inv = power(n, mod - 2);
  for (int i = 0; i < n; i++) {
    R[i] = (R[i >> 1] >> 1) | ((i & 1) << (d - 1));
  }
  for (int i = as; i < n; i++)
    A[i] = 0;
  for (int i = bs; i < n; i++)
    B[i] = 0;
  NTT(A, n, 0), NTT(B, n, 0);
  for (int i = 0; i < n; i++)
    A[i] = A[i] * B[i] % mod;
  NTT(A, n, 1);
  c.clear();
  for (int i = 0; i <= as + bs - 2; i++)
    c.push_back(A[i] % mod);
}
void init() {
  fac[0] = fac[1] = finv[0] = 1;
  two[0] = 1;
  two[1] = (mod + 1) / 2;
  for (int i = 2; i < N; ++i) {
    fac[i] = 1ll * fac[i - 1] * i % mod;
    two[i] = 1ll * two[i - 1] * two[1] % mod;
  }
  finv[N - 1] = power(fac[N - 1], mod - 2);
  for (int i = N - 2; i >= 1; --i)
    finv[i] = 1ll * finv[i + 1] * (i + 1) % mod;
}
int C(int n, int m) {
  if (m < 0 || n < m)
    return 0;
  return 1ll * fac[n] * finv[m] % mod * finv[n - m] % mod;
}
int cal(int x) { return 1ll * fac[2 * x] * two[x] % mod * finv[x] % mod; }
int main() {
  init();
  scanf("%d", &n);
  int mx = 0;
  for (int i = 1; i <= 2 * n; ++i) {
    int v;
    scanf("%d", &v);
    mx = max(mx, v);
    tong[v]++;
  }
  int sz = 0;
  for (int i = 1; i <= mx; i++) {
    if (tong[i] < 2)
      continue;
    colors[++sz].clear();
    int up = tong[i] / 2;
    colors[sz].push_back(1);
    int now = 1, left = tong[i], v;
    for (int j = 1; j <= up; ++j) {
      now = 1ll * now * C(left, 2) % mod;
      v = 1ll * now * finv[j] % mod;
      colors[sz].push_back(v);
      left -= 2;
    }
    heap.push(sz);
  }
  while (heap.size() >= 2) {
    int x = heap.top();
    heap.pop();
    int y = heap.top();
    heap.pop();
    NTT_times(colors[x], colors[y], colors[++sz]);
    colors[x].clear(), colors[y].clear();
    heap.push(sz);
  }
  ll ans = cal(n);
  for (int i = 1; i < colors[sz].size(); ++i) {
    ll v = 1ll * colors[sz][i] * cal(n - i) % mod;
    if (i & 1) {
      ans = (ans - v + mod) % mod;
    } else {
      ans = (ans + v) % mod;
    }
  }

  printf("%lld", ans);
  return 0;
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

const int P = 998244353;

class Comb {
public:
  vector<int> fac;
  vector<int> inv;
  vector<int> facinv;
  int P;

  Comb() {}
  Comb(int N, int P) : fac(N + 1), inv(N + 1), facinv(N + 1), P(P) {
    fac[0] = 1;
    for (int i = 1; i <= N; ++i) {
      fac[i] = 1LL * fac[i - 1] * i % P;
    }
    inv[1] = 1;
    for (int i = 2; i <= N; ++i) {
      inv[i] = 1LL * (P - P / i) * inv[P % i] % P;
    }
    facinv[0] = 1;
    for (int i = 1; i <= N; ++i) {
      facinv[i] = 1LL * facinv[i - 1] * inv[i] % P;
    }
  }

  int C(int n, int m) {
    if (n < m) {
      return 0;
    }
    return 1LL * fac[n] * facinv[m] % P * facinv[n - m] % P;
  }

  int Inv(int n) { return inv[n]; }
};

namespace poly { // method : use c = multiply(a, b)
vector<int> rev = {0, 1};
vector<int> Root = {0, 1};

const int P = 998244353;
const int G = 3;

int power(int x, int t) {
  int ret = 1;
  for (; t; t >>= 1, x = 1LL * x * x % P) {
    if (t & 1) {
      ret = 1LL * ret * x % P;
    }
  }
  return ret;
}

void init(int n) {
  if (n <= Root.size()) {
    return;
  }
  rev.resize(n);
  for (int i = 0; i < n; ++i) {
    rev[i] = (rev[i >> 1] | ((i & 1) * n)) >> 1;
  }
  if ((int)Root.size() < n) {
    int k = __builtin_ctz(Root.size());
    Root.resize(n);
    while ((1 << k) < n) {
      int z = power(G, (P - 1) >> (k + 1));
      for (int i = 1 << (k - 1); i < (1 << k); ++i) {
        Root[2 * i] = Root[i];
        Root[2 * i + 1] = 1LL * Root[i] * z % P;
      }
      k += 1;
    }
  }
}

void dft(vector<int> &a, int n) {
  init(n);
  int s = __builtin_ctz(rev.size() / n);
  for (int i = 0; i < n; ++i) {
    if (i < rev[i] >> s) {
      swap(a[i], a[rev[i] >> s]);
    }
  }
  for (int k = 1; k < n; k = k * 2) {
    for (int i = 0; i < n; i = i + k * 2) {
      for (int j = 0; j < k; ++j) {
        int t = 1LL * Root[j + k] * a[i + j + k] % P;
        a[i + j + k] = (a[i + j] - t + P) % P;
        a[i + j] = (a[i + j] + t) % P;
      }
    }
  }
}

void idft(vector<int> &a, int n) {
  reverse(a.begin() + 1, a.end());
  dft(a, n);
  int inv = power(n, P - 2);
  for (int i = 0; i < n; ++i) {
    a[i] = 1LL * a[i] * inv % P;
  }
}

vector<int> multiply(vector<int> a,
                     vector<int> b) { // return a * b size = sz(a) + sz(b)
  int s = a.size() + b.size() - 1;
  if (s <= 0) {
    return {};
  }
  int L = s > 1 ? 32 - __builtin_clz(s - 1) : 0;
  int n = 1 << L;
  a.resize(n);
  dft(a, n);
  b.resize(n);
  dft(b, n);
  for (int i = 0; i < n; ++i) {
    a[i] = 1LL * a[i] * b[i] % P;
  }
  idft(a, n);
  a.resize(s);
  return a;
}
} // namespace poly

long long power(long long x, long long t) {
  long long ret = 1;
  for (; t; t >>= 1, x = x * x % P) {
    if (t & 1) {
      ret = ret * x % P;
    }
  }
  return ret;
}

class Poly {
public:
  vector<int> a;

  Poly() {}
  Poly(const vector<int> &_a) : a(_a) {}

  bool friend operator<(const Poly &a, const Poly &b) {
    return a.a.size() > b.a.size();
  }
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n;
  cin >> n;

  int v;
  vector<int> cnt(100005);
  for (int i = 0; i < n * 2; ++i) {
    cin >> v;
    cnt[v]++;
  }

  Comb C(n * 2 + 2, P);
  priority_queue<Poly> q;

  auto calc = [&](int n) {
    long long tmp = power(2, n);
    return 1LL * C.fac[2 * n] * C.facinv[n] % P * power(tmp, P - 2) % P;
  };

  for (int i = 0; i < 100005; ++i) {
    if (cnt[i] >= 2) {
      Poly tmp;
      tmp.a.resize(cnt[i] / 2 + 2);
      for (int j = 0; j + j <= cnt[i]; ++j) {
        long long x = C.C(cnt[i], j * 2);
        tmp.a[j] = x * calc(j) % P;
      }
      q.emplace(tmp);
    }
  }

  while (q.size() > 1) {
    Poly a = q.top();
    q.pop();
    Poly b = q.top();
    q.pop();
    Poly c;
    c.a = poly::multiply(a.a, b.a);
    q.emplace(c);
  }

  vector<int> dp = q.top().a;

  long long ans = 0;
  for (int i = 0; i < min(n + 1, (int)dp.size()); ++i) {
    dp[i] = 1LL * dp[i] * calc(n - i) % P;
    ans = (ans + 1LL * (i % 2 == 0 ? 1 : -1) * dp[i] + P) % P;
  }

  cout << ans << '\\n';

  return 0;
}