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

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#define int long long
#define PII pair<int, int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
inline int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = (x << 3) + (x << 1) + (c ^ 48);
    c = getchar();
  }
  return f == 1 ? x : -x;
}
inline void print(int x) {
  if (x < 0)
    x = ~x + 1, putchar('-');
  if (x >= 10)
    print(x / 10);
  putchar((x % 10) | 48);
}
priority_queue<PII, vector<PII>, greater<PII>> Q;
int n;
int m;
int cnt[100010];
int tmp[100010];
vector<int> vec[200010];
int fac[100010], ifac[100010];
int R[200010];
int a[200010], b[200010];
int x = 1, len;
const int mod = 998244353;
int num;
int qpow(int x, int k) {
  int res = 1;
  while (k) {
    if (k & 1)
      res = 1ll * res * x % mod;
    x = 1ll * x * x % mod;
    k >>= 1;
  }
  return res;
}
inline int C(int x, int y) {
  if (x == 0 || y == 0)
    return 1;
  return 1ll * fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
void NTT(int s[], int f) {
  for (int i = 0; i <= x; i++)
    if (i < R[i])
      swap(s[i], s[R[i]]);
  for (int l = 1; l < x; l <<= 1) {
    int w;
    if (f == 1)
      w = qpow(3, (mod - 1) / (l << 1));
    else
      w = qpow(qpow(3, mod - 2), (mod - 1) / (l << 1));
    for (int j = 0; j < x; j += (l << 1)) {
      int sum = 1;
      for (int k = 0; k < l; k++) {
        int a1 = s[j + k], a2 = sum * s[j + l + k] % mod;
        s[j + k] = (a1 + a2) % mod, s[j + l + k] = (a1 - a2 + mod) % mod;
        sum = sum * w % mod;
      }
    }
  }
}
signed main() {
  n = read();
  n <<= 1;
  fac[1] = 1;
  fac[0] = 1;
  for (int i = 2; i <= n; ++i)
    fac[i] = 1ll * fac[i - 1] * i % mod;
  ifac[n] = qpow(fac[n], mod - 2);
  for (int i = n - 1; i >= 0; --i)
    ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
  //	printf("%d %d %d %d\\n",ifac[1],ifac[2],ifac[3],ifac[4]);
  //	printf("%d %d\\n",C(2,1),C(1,1));
  //	printf("%d\\n",ifac[1]);
  for (int i = 1; i <= n; ++i)
    tmp[i] = read();
  sort(tmp + 1, tmp + n + 1);
  for (int i = 1; i <= n; ++i) {
    if (tmp[i] != tmp[i - 1])
      cnt[++m] = 1;
    else
      ++cnt[m];
  }
  for (int i = 1; i <= m; ++i) {
    for (int j = 0; j <= (cnt[i] >> 1); ++j) {
      vec[i].pb(1ll * C(cnt[i], j) * C(cnt[i] - j, j) % mod * fac[j] % mod *
                qpow(qpow(2, j), mod - 2) % mod);
      //			printf("i:%d,j:%d,cnt:%d,v:%d\\n",i,j,cnt[i],vec[i][j]);
      //			printf("%d %d %d
      //%d\\n",C(cnt[i],j),C(cnt[i]-j,j),fac[j],qpow(2,j));
    }
    Q.push(mp(vec[i].size(), i));
  }
  num = m;
  int ans = 0;
  while (Q.size() > 1) {
    int u = Q.top().se;
    Q.pop();
    int v = Q.top().se;
    Q.pop();
    int N = vec[u].size(), M = vec[v].size();
    x = 1, len = 0;
    while (x <= N + M - 2)
      x <<= 1, len++;
    for (int i = 0; i <= x; i++)
      R[i] = (R[i >> 1] >> 1) | ((i & 1) << len - 1);
    for (int i = 0; i <= x; ++i)
      a[i] = b[i] = 0;
    for (int i = 0; i < N; ++i)
      a[i] = vec[u][i];
    for (int i = 0; i < M; ++i)
      b[i] = vec[v][i];
    NTT(a, 1), NTT(b, 1);
    for (int i = 0; i <= x; i++)
      a[i] = 1ll * a[i] * b[i] % mod;
    //		printf("u:%d,v:%d\\n",u,v);
    //		for(int i=0;i<=N+M-2;++i)
    //printf("%d\\n",1ll*a[i]*qpow(x,mod-2)%mod);
    NTT(a, -1);
    ++num;
    if (!Q.size()) {
      //			ans=1ll*C(n,n>>1)*fac[n>>1]%mod*qpow(qpow(2,n>>1),mod-2)%mod;
      for (int i = 0; i <= N + M - 2; ++i)
        (ans += qpow(-1, i) * a[i] * qpow(x, mod - 2) % mod *
                C(n - 2 * i, (n - 2 * i) >> 1) % mod * fac[(n - 2 * i) >> 1] %
                mod * qpow(qpow(2, (n - 2 * i) >> 1), mod - 2) % mod) %= mod;
      break;
    }
    for (int i = 0; i <= N + M - 2; ++i)
      vec[num].pb(1ll * a[i] * qpow(x, mod - 2) % mod);
    Q.push(mp(vec[num].size(), num));
  }
  printf("%lld\\n", (ans + mod) % mod);
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
#define PII pair<int, int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
inline int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-')
      f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = (x << 3) + (x << 1) + (c ^ 48);
    c = getchar();
  }
  return f == 1 ? x : -x;
}
inline void print(int x) {
  if (x < 0)
    x = ~x + 1, putchar('-');
  if (x >= 10)
    print(x / 10);
  putchar((x % 10) | 48);
}
int n, m;
int h[100010];
int tmp[100010];
int cnt[100010];
map<PII, int> ma;
int fac[100010], ifac[100010];
const int mod = 998244353;
inline int C(int x, int y) {
  if (x == 0 || y == 0)
    return 1;
  return 1ll * fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
int sum[100010];
inline int dp(int i, int j) {
  if (j > sum[i] || j > n - sum[i + 1])
    return 0;
  if ((j & 1) != ((n - sum[i + 1]) & 1))
    return 0;
  if (j < 0)
    return 0;
  if (ma.count(mp(i, j)))
    return ma[mp(i, j)];
  if (i == 0)
    return 0;
  //	printf("i:%d,j:%d\\n",i,j);
  for (int k = 0; k <= cnt[i] && k <= n - sum[i]; ++k) {
    //		printf("k:%d\\n",k);
    ma[mp(i, j)] += 1ll * dp(i - 1, j - (cnt[i] - k) + k) * C(cnt[i], k) % mod *
                    C(j - (cnt[i] - k) + k, k) % mod * fac[k] % mod;
  }
  //	printf("out:i:%d,j:%d\\n",i,j);
  return ma[mp(i, j)];
}
int qpow(int x, int k) {
  int res = 1;
  while (k) {
    if (k & 1)
      res = 1ll * res * x % mod;
    x = 1ll * x * x % mod;
    k >>= 1;
  }
  return res;
}
int main() {
  n = read();
  n <<= 1;
  ma[mp(0, 0)] = 1;
  fac[1] = 1;
  fac[0] = 1;
  for (int i = 2; i <= n; ++i)
    fac[i] = 1ll * fac[i - 1] * i % mod;
  ifac[n] = qpow(fac[n], mod - 2);
  for (int i = n - 1; i >= 0; --i)
    ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
  for (int i = 1; i <= n; ++i)
    tmp[i] = read();
  sort(tmp + 1, tmp + n + 1);
  for (int i = 1; i <= n; ++i) {
    if (tmp[i] != tmp[i - 1])
      cnt[++m] = 1;
    else
      cnt[m]++;
  }
  for (int i = m; i >= 1; --i)
    sum[i] = sum[i + 1] + cnt[i];
  //	for(int i=1;i<=m;++i) printf("cnt:%d\\n",cnt[i]);
  //	printf("%d\\n",C(2,2));
  //	printf("%d\\n",dp(1,0));
  printf("%d\\n", dp(m, 0));
  //	printf("%d\\n",dp(2,1));
  return 0;
}