Problem p02539 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
#define watch(x) std::cout << (#x) << " is " << (x) << std::endl
#define print(x) std::cout << (x) << std::endl
#define println std::cout << std::endl;
using LL = long long;

const LL M = 998244353, ROOT = 3;
LL powMod(LL x, LL n) {
  LL r(1);
  while (n) {
    if (n & 1)
      r = r * x % M;
    n >>= 1;
    x = x * x % M;
  }
  return r;
}
void bitreverse(std::vector<LL> &a) {
  for (int i = 0, j = 0; i != a.size(); ++i) {
    if (i > j)
      std::swap(a[i], a[j]);
    for (int l = a.size() >> 1; (j ^= l) < l; l >>= 1)
      ;
  }
}
void nft(std::vector<LL> &a, bool isInverse = false) {
  LL g = powMod(ROOT, (M - 1) / a.size());
  if (isInverse) {
    g = powMod(g, M - 2);
    LL invLen = powMod(LL(a.size()), M - 2);
    for (auto &x : a)
      x = x * invLen % M;
  }
  bitreverse(a);
  std::vector<LL> w(a.size(), 1);
  for (int i = 1; i != w.size(); ++i)
    w[i] = w[i - 1] * g % M;
  auto addMod = [](LL x, LL y) { return (x += y) >= M ? x -= M : x; };
  for (int step = 2, half = 1; half != a.size(); step <<= 1, half <<= 1) {
    for (int i = 0, wstep = a.size() / step; i != a.size(); i += step) {
      for (int j = i; j != i + half; ++j) {
        LL t = (a[j + half] * w[wstep * (j - i)]) % M;
        a[j + half] = addMod(a[j], M - t);
        a[j] = addMod(a[j], t);
      }
    }
  }
}
void mul(std::vector<LL> &a, std::vector<LL> b) {
  int sz = 1, tot = a.size() + b.size() - 1;
  while (sz < tot)
    sz *= 2;
  a.resize(sz);
  b.resize(sz);
  nft(a);
  nft(b);
  for (int i = 0; i != sz; ++i)
    a[i] = a[i] * b[i] % M;
  nft(a, 1);
  a.resize(tot);
}
const int N = 1e5 + 2;
LL fac[N], ifac[N];
LL inv(LL a) { // 0 < a < p and gcd(a,p) = 1
  return a == 1 ? 1 : (M - M / a) * inv(M % a) % M;
}
void init() {
  fac[0] = ifac[0] = 1;
  for (int i = 1; i < N; ++i)
    fac[i] = fac[i - 1] * i % M;
  ifac[N - 1] = inv(fac[N - 1]);
  for (int i = N - 1; i; --i)
    ifac[i - 1] = ifac[i] * i % M;
}
LL binom(int n, int k) {
  if (n < k)
    return 0;
  return fac[n] * ifac[k] % M * ifac[n - k] % M;
}
int main() {
  // freopen("in","r",stdin);
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  init();
  int n;
  std::cin >> n;
  std::vector<int> cnt(1e5 + 2);
  for (int i = 0, x; i < 2 * n; ++i) {
    std::cin >> x;
    ++cnt[x];
  }
  std::vector<LL> r(1, 1);
  LL inv2 = (M + 1) / 2;
  std::sort(cnt.begin(), cnt.end());
  auto start = std::lower_bound(cnt.begin(), cnt.end(), 1) - cnt.begin();
  std::vector<std::pair<int, int>> q;
  q.push_back({cnt[start], 1});
  for (int i = start + 1; i < cnt.size(); ++i) {
    if (cnt[i] != q.back().first)
      q.push_back({cnt[i], 1});
    else
      ++q.back().second;
  }
  for (auto [x, xn] : q)
    if (x > 0) {
      std::vector<LL> a(x / 2 + 1);
      LL p2j = 1;
      for (int j = 0; j <= x / 2; ++j) {
        a[j] = fac[x] * ifac[x - 2 * j] % M * ifac[j] % M * p2j % M;
        p2j = p2j * inv2 % M;
      }
      while (xn) {
        if (xn & 1)
          mul(r, a);
        xn >>= 1;
        mul(a, a);
      }
    }
  std::vector<LL> G(n + 1);
  G[0] = 1;
  for (int i = 1; i <= n; ++i)
    G[i] = G[i - 1] * (2 * i - 1) % M;
  LL ret = 0;
  for (int i = 0; i < r.size() && i <= n; ++i) {
    ret += (i % 2 == 1 ? -1 : 1) * G[n - i] * r[i] % M;
  }
  print((ret % M + M) % M);
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define watch(x) std::cout << (#x) << " is " << (x) << std::endl
#define print(x) std::cout << (x) << std::endl
#define println std::cout << std::endl;
using LL = long long;

const LL M = 998244353, ROOT = 3;
LL powMod(LL x, LL n) {
  LL r(1);
  while (n) {
    if (n & 1)
      r = r * x % M;
    n >>= 1;
    x = x * x % M;
  }
  return r;
}
void bitreverse(std::vector<LL> &a) {
  for (int i = 0, j = 0; i != a.size(); ++i) {
    if (i > j)
      std::swap(a[i], a[j]);
    for (int l = a.size() >> 1; (j ^= l) < l; l >>= 1)
      ;
  }
}
void nft(std::vector<LL> &a, bool isInverse = false) {
  LL g = powMod(ROOT, (M - 1) / a.size());
  if (isInverse) {
    g = powMod(g, M - 2);
    LL invLen = powMod(LL(a.size()), M - 2);
    for (auto &x : a)
      x = x * invLen % M;
  }
  bitreverse(a);
  std::vector<LL> w(a.size(), 1);
  for (int i = 1; i != w.size(); ++i)
    w[i] = w[i - 1] * g % M;
  auto addMod = [](LL x, LL y) { return (x += y) >= M ? x -= M : x; };
  for (int step = 2, half = 1; half != a.size(); step <<= 1, half <<= 1) {
    for (int i = 0, wstep = a.size() / step; i != a.size(); i += step) {
      for (int j = i; j != i + half; ++j) {
        LL t = (a[j + half] * w[wstep * (j - i)]) % M;
        a[j + half] = addMod(a[j], M - t);
        a[j] = addMod(a[j], t);
      }
    }
  }
}
void mul(std::vector<LL> &a, std::vector<LL> b) {
  int sz = 1, tot = a.size() + b.size() - 1;
  while (sz < tot)
    sz *= 2;
  a.resize(sz);
  b.resize(sz);
  nft(a);
  nft(b);
  for (int i = 0; i != sz; ++i)
    a[i] = a[i] * b[i] % M;
  nft(a, 1);
  a.resize(tot);
}
const int N = 1e5 + 2;
LL fac[N], ifac[N];
LL inv(LL a) { // 0 < a < p and gcd(a,p) = 1
  return a == 1 ? 1 : (M - M / a) * inv(M % a) % M;
}
void init() {
  fac[0] = ifac[0] = 1;
  for (int i = 1; i < N; ++i)
    fac[i] = fac[i - 1] * i % M;
  ifac[N - 1] = inv(fac[N - 1]);
  for (int i = N - 1; i; --i)
    ifac[i - 1] = ifac[i] * i % M;
}
LL binom(int n, int k) {
  if (n < k)
    return 0;
  return fac[n] * ifac[k] % M * ifac[n - k] % M;
}
int main() {
  // freopen("in","r",stdin);
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  init();
  int n;
  std::cin >> n;
  std::vector<int> cnt(1e5 + 2);
  for (int i = 0, x; i < 2 * n; ++i) {
    std::cin >> x;
    ++cnt[x];
  }
  std::vector<LL> r(1, 1);
  LL inv2 = (M + 1) / 2;
  std::sort(cnt.begin(), cnt.end());
  auto start = std::lower_bound(cnt.begin(), cnt.end(), 1);
  cnt = std::vector<int>(start, cnt.end());
  for (auto x : cnt)
    if (x > 0) {
      std::vector<LL> a(x / 2 + 1);
      LL p2j = 1;
      for (int j = 0; j <= x / 2; ++j) {
        a[j] = fac[x] * ifac[x - 2 * j] % M * ifac[j] % M * p2j % M;
        p2j = p2j * inv2 % M;
      }
      mul(r, a);
    }
  std::vector<LL> G(n + 1);
  G[0] = 1;
  for (int i = 1; i <= n; ++i)
    G[i] = G[i - 1] * (2 * i - 1) % M;
  LL ret = 0;
  for (int i = 0; i < r.size() && i <= n; ++i) {
    ret += (i % 2 == 1 ? -1 : 1) * G[n - i] * r[i] % M;
  }
  print((ret % M + M) % M);
  return 0;
}