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

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;
const int g = 3;
const int N = 65536;

int a[100010];
int res[100010];
int f[100010], t[100010];
int cnt[100010];
long long fac[100010], inv[100010], ways[100010];
int num[100010];

long long power(int a, int b) {
  if (!b)
    return 1;
  long long tmp = power(a, b >> 1);
  return b & 1 ? tmp * tmp % mod * a % mod : tmp * tmp % mod;
}

void NTT(int *a, int N, int *f, int flag) {
  for (int i = 0; i < N; i++) {
    f[i] = a[num[i]];
  }
  for (int len = 2; len <= N; len <<= 1) {
    long long E = power(g, (mod - 1) / len);
    if (flag)
      E = power(E, mod - 2);
    for (int i = 0; i < N; i += len) {
      long long now = 1;
      for (int j = i; j < i + (len >> 1); j++) {
        long long tmp = now * f[j + (len >> 1)] % mod;
        f[j + (len >> 1)] = f[j] - tmp;
        if (f[j + (len >> 1)] < 0)
          f[j + (len >> 1)] += mod;
        f[j] = f[j] + tmp;
        if (f[j] >= mod)
          f[j] -= mod;
        now = now * E % mod;
      }
    }
  }
  if (flag) {
    long long inv = power(N, mod - 2);
    for (int i = 0; i < N; i++) {
      f[i] = f[i] * inv % mod;
    }
  }
}

long long C(int n, int k) { return fac[n] * inv[k] % mod * inv[n - k] % mod; }

int main() {
  fac[0] = inv[0] = 1, ways[0] = 1;
  for (int i = 1; i <= 100000; i++) {
    fac[i] = fac[i - 1] * i % mod;
    inv[i] = power(fac[i], mod - 2);
    ways[i] = (2 * i - 1) * ways[i - 1] % mod;
  }
  int n;
  scanf("%d", &n), n <<= 1;
  for (int i = 0; i < n; i++) {
    int x;
    scanf("%d", &x);
    cnt[x]++;
  }
  for (int i = 0; i < N; i++) {
    num[i] = num[i >> 1] >> 1 | (i & 1 ? N >> 1 : 0);
  }
  f[0] = 1;
  NTT(f, N, res, 0);
  for (int i = 1; i <= 100000; i++) {
    a[cnt[i]]++;
  }
  for (int i = 1; i <= 100000; i++) {
    if (!a[i])
      continue;
    memset(f, 0, sizeof(f));
    for (int j = 0; j * 2 <= i; j++) {
      f[j] = C(i, j * 2) * ways[j] % mod;
    }
    NTT(f, N, t, 0);
    for (int j = 0; j < N; j++) {
      res[j] = 1ll * res[j] * power(t[j], a[i]) % mod;
    }
  }
  NTT(res, N, f, 1);
  long long ans = 0;
  for (int i = 0; i < N; i++) {
    if (2 * i > n)
      break;
    long long tmp = 1ll * f[i] * ways[n - 2 * i >> 1] % mod;
    ans = (ans + (i & 1 ? -1 : 1) * tmp + mod) % mod;
  }
  printf("%lld\\n", ans);
  return 0;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;
const int g = 3;
const int N = 65536;

int a[100010];
int res[100010];
int f[100010], t[100010];
long long fac[100010], inv[100010], ways[100010];
int num[100010];

long long power(int a, int b) {
  if (!b)
    return 1;
  long long tmp = power(a, b >> 1);
  return b & 1 ? tmp * tmp % mod * a % mod : tmp * tmp % mod;
}

void NTT(int *a, int N, int *f, int flag) {
  for (int i = 0; i < N; i++) {
    f[i] = a[num[i]];
  }
  for (int len = 2; len <= N; len <<= 1) {
    long long E = power(g, (mod - 1) / len);
    if (flag)
      E = power(E, mod - 2);
    for (int i = 0; i < N; i += len) {
      long long now = 1;
      for (int j = i; j < i + (len >> 1); j++) {
        long long tmp = now * f[j + (len >> 1)] % mod;
        f[j + (len >> 1)] = f[j] - tmp;
        if (f[j + (len >> 1)] < 0)
          f[j + (len >> 1)] += mod;
        f[j] = f[j] + tmp;
        if (f[j] >= mod)
          f[j] -= mod;
        now = now * E % mod;
      }
    }
  }
  if (flag) {
    long long inv = power(N, mod - 2);
    for (int i = 0; i < N; i++) {
      f[i] = f[i] * inv % mod;
    }
  }
}

long long C(int n, int k) { return fac[n] * inv[k] % mod * inv[n - k] % mod; }

int main() {
  fac[0] = inv[0] = 1, ways[0] = 1;
  for (int i = 1; i <= 100000; i++) {
    fac[i] = fac[i - 1] * i % mod;
    inv[i] = power(fac[i], mod - 2);
    ways[i] = (2 * i - 1) * ways[i - 1] % mod;
  }
  int n;
  scanf("%d", &n), n <<= 1;
  for (int i = 0; i < n; i++) {
    int x;
    scanf("%d", &x);
    a[x]++;
  }
  for (int i = 0; i < N; i++) {
    num[i] = num[i >> 1] >> 1 | (i & 1 ? N >> 1 : 0);
  }
  f[0] = 1;
  NTT(f, N, res, 0);
  for (int i = 1; i <= 100000; i++) {
    if (!a[i])
      continue;
    memset(f, 0, sizeof(f));
    for (int j = 0; j * 2 <= a[i]; j++) {
      f[j] = C(a[i], j * 2) * ways[j] % mod;
    }
    NTT(f, N, t, 0);
    for (int j = 0; j < N; j++) {
      res[j] = 1ll * res[j] * t[j] % mod;
    }
  }
  NTT(res, N, f, 1);
  long long ans = 0;
  for (int i = 0; i < N; i++) {
    if (2 * i > n)
      break;
    long long tmp = 1ll * f[i] * ways[n - 2 * i >> 1] % mod;
    ans = (ans + (i & 1 ? -1 : 1) * tmp + mod) % mod;
  }
  printf("%lld\\n", ans);
  return 0;
}