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

#include <bits/stdc++.h>

#define ln '\\n'
#define all(dat) dat.begin(), dat.end()
#define loop(i, to) for (int i = 0; i < to; ++i)
#define cont(i, to) for (int i = 1; i <= to; ++i)
#define circ(i, fm, to) for (int i = fm; i <= to; ++i)
#define foreach(i, dat)                                                        \\
  for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long num;

using namespace std;

template <int mod> struct modulo;
template <int mod> struct modulo_cplx;

template <int mod> struct modulo_cplx {
  modulo<mod> a, b, i2;

  modulo_cplx() {}
  modulo_cplx(modulo<mod> a, modulo<mod> b, modulo<mod> i2 = 0) {
    this->a = a, this->b = b;
    this->i2 = i2;
  }

  inline modulo_cplx operator*(const modulo_cplx &d) {
    return modulo_cplx(a * d.a + i2 * b * d.b, a * d.b + b * d.a, i2);
  }
  inline modulo_cplx &operator*=(const modulo_cplx &d) {
    return *this = *this * d;
  }

  friend inline modulo_cplx pow(const modulo_cplx &w, int p) {
    if (w.a == 0 && w.b == 0)
      return modulo_cplx(0, 0, w.i2);
    modulo_cplx a = w, r = modulo_cplx(1, 0, w.i2);
    for (; p > 0; a *= a, p >>= 1)
      if (p & 1)
        r *= a;
    return r;
  }
};

template <int mod> struct modulo {
  int w;
  operator int &() { return w; }
  operator int() const { return w; }

  modulo() {}
  modulo(int w, bool f = 0) {
    this->w = w;
    if (f)
      fix();
  }
  void inline fix() {
    if (w >= mod || w < -mod)
      w %= mod;
    if (w < 0)
      w += mod;
  }

  inline modulo operator-() {
    w = mod - w;
    if (w >= mod)
      w -= mod;
    return *this;
  }
  inline modulo operator+(const modulo &b) {
    modulo r = *this;
    return r += b;
  }
  inline modulo operator-(const modulo &b) {
    modulo r = *this;
    return r -= b;
  }
  inline modulo operator*(const modulo &b) {
    modulo r = *this;
    return r *= b;
  }
  inline modulo operator/(const modulo &b) {
    modulo r = *this;
    return r /= b;
  }
  inline modulo &operator+=(const modulo &b) {
    if ((w += b.w) >= mod)
      w -= mod;
    return *this;
  }
  inline modulo &operator-=(const modulo &b) {
    if ((w -= b.w) < 0)
      w += mod;
    return *this;
  }
  inline modulo &operator*=(const modulo &b) {
    w = (num)w * b.w % mod;
    return *this;
  }
  inline modulo &operator/=(const modulo &b) { return *this *= inv(b); }

  friend inline modulo inv(const modulo &w) {
    int a = w, m = mod, u = 0, v = 1, t;
    for (; a != 0; t = m / a, m -= t * a, swap(a, m), u -= t * v, swap(u, v))
      ;
    return modulo(u, 1);
  }

  friend inline modulo pow(const modulo &w, int p) {
    if (!w)
      return 0;
    modulo a = w, r = 1;
    for (; p > 0; a *= a, p >>= 1)
      if (p & 1)
        r *= a;
    return r;
  }

  friend inline modulo sqrt(const modulo &w) {
    int k = (mod - 1) / 2;
    assert(pow(w, k) == 1);
    modulo a = rand() % mod;
    for (; pow(a * a - w, k) != mod - 1; a = rand() % mod)
      ;
    modulo_cplx<mod> t(a, 1, a * a - w);
    modulo r = pow(t, (mod + 1) / 2).a;
    return min(int(r), int(mod - r));
  }
};
const int mod = 998244353, mod_root = 3;
typedef modulo<mod> rem;
typedef unsigned long long u64;

const int degsz = int(4e5);

template <class type> struct fourier_transform;
template <class type> struct poly;

template <class type> struct fourier_transform {
  int k, sz, rev[degsz + 5];
  u64 b[degsz + 5], pw[degsz + 5];

  void inline init(int to) {
    for (sz = 1, k = 0; sz <= to; sz <<= 1, ++k)
      ;
    if (k == 0)
      return;
    loop(i, sz) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
  }

  void inline dft(poly<type> &a, int tp = 1) {
    a.set_deg(sz - 1);
    loop(i, sz) {
      b[i] = a[i];
      if (i > rev[i])
        swap(b[i], b[rev[i]]);
    }
    for (int len = 1; len < sz; len <<= 1) {
      int w0 = pow(rem(mod_root), (mod - 1) / (len << 1));
      if (tp == -1)
        w0 = inv(rem(w0));
      pw[0] = 1;
      cont(i, len - 1) pw[i] = pw[i - 1] * w0 % mod;
      for (int l = 0; l < sz; l += len << 1) {
        u64 *p0 = b + l, *p1 = b + l + len, *w = pw, tmp;
        for (int i = 0; i < len; ++i, ++p0, ++p1, ++w) {
          tmp = *w * *p1 % mod;
          *p1 = *p0 + mod - tmp;
          *p0 += tmp;
        }
      }
    }
    loop(i, sz) a[i] = b[i] % mod;
    if (tp == -1) {
      rem rs = inv(rem(sz));
      loop(i, sz) a[i] *= rs;
    }
  }
};
fourier_transform<rem> ft;

template <class type> struct poly {
  int deg;
  vector<type> d;

  poly() { deg = 0; }
  poly(type a) { deg = 0, d.push_back(a); }
  poly(vector<type> a) { deg = int(a.size()) - 1, d = a; }

  void inline set_deg(int sz) { deg = sz, d.resize(sz + 1, 0); }

  void inline fix() {
    for (; d.size() && d.back() == 0; d.pop_back(), --deg)
      ;
  }

  inline type &operator[](int id) { return d[id]; }
  inline type operator[](int id) const { return d[id]; }

  inline type operator()(int x) const {
    if (x == 0)
      return d[0];
    int r = 0;
    for (int i = deg; i >= 0; --i)
      r *= x, r += d[i];
    return r;
  }

  friend inline poly operator+(const poly &a, const poly &b) {
    poly r;
    r.set_deg(max(a.deg, b.deg));
    circ(i, 0, r.deg) r[i] =
        (i <= a.deg ? a[i] : type(0)) + (i <= b.deg ? b[i] : type(0));
    return r;
  }
  friend inline poly operator+(const poly &a, const type &b) {
    poly r = a;
    r[0] += b;
    return r;
  }
  friend inline poly operator+(const type &a, const poly &b) { return b + a; }
  friend inline poly operator+=(poly &a, const poly &b) { return a = a + b; }
  friend inline poly operator+=(poly &a, const type &b) { return a = a + b; }

  friend inline poly operator-(const poly &a, const poly &b) {
    poly r;
    r.set_deg(max(a.deg, b.deg));
    circ(i, 0, r.deg) r[i] =
        (i <= a.deg ? a[i] : type(0)) - (i <= b.deg ? b[i] : type(0));
    return r;
  }
  friend inline poly operator-(const poly &a, const type &b) {
    poly r = a;
    r[0] -= b;
    return r;
  }
  friend inline poly operator-(const type &a, const poly &b) {
    poly r = b - a;
    circ(i, 0, r.deg) r[i] = -r[i];
    return r;
  }
  friend inline poly operator-=(poly &a, const poly &b) { return a = a - b; }
  friend inline poly operator-=(poly &a, const type &b) { return a = a - b; }

  friend inline poly operator*(const poly &a, const poly &b) {
    poly f = a, g = b;
    ft.init(a.deg + b.deg);
    ft.dft(f), ft.dft(g);
    loop(i, ft.sz) f[i] *= g[i];
    ft.dft(f, -1);
    f.set_deg(a.deg + b.deg);
    return f;
  }
  friend inline poly operator*(const poly &a, const type &b) {
    poly r = a;
    circ(i, 0, r.deg) r[i] *= b;
    return r;
  }
  friend inline poly operator*(const type &a, const poly &b) { return b * a; }
  friend inline poly operator*=(poly &a, const poly &b) { return a = a * b; }
  friend inline poly operator*=(poly &a, const type &b) { return a = a * b; }

  friend inline poly operator/(const poly &a, const poly &b) {
    int sz = a.deg - b.deg;
    poly f = a, g = b;
    if (a.deg < b.deg)
      return poly(0);
    reverse(all(f.d)), reverse(all(g.d));
    f.set_deg(sz), g.set_deg(sz);
    f *= inv(g);
    f.set_deg(sz);
    reverse(all(f.d));
    return f;
  }
  friend inline poly operator/=(poly &a, const poly &b) { return a = a / b; }

  friend inline poly operator%(const poly &a, const poly &b) {
    poly r = a - b * (a / b);
    r.set_deg(b.deg - 1);
    return r;
  }
  friend inline poly operator%=(poly &a, const poly &b) { return a = a % b; }

  friend poly inv(const poly &a) {
    if (a.deg == 0)
      return inv(a[0]);
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = inv(b);

    b = a;
    ft.init(2 * a.deg);
    ft.dft(b), ft.dft(r);
    loop(i, ft.sz) r[i] *= (type(2) - r[i] * b[i]);
    ft.dft(r, -1);

    r.set_deg(a.deg);
    return r;
  }

  friend poly sqrt(const poly &a) {
    if (a.deg == 0)
      return sqrt(type(a[0]));
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = sqrt(b);

    r.set_deg(a.deg);
    r = (r + a * inv(r)) * inv(type(2));

    r.set_deg(a.deg);
    return r;
  }

  friend inline poly derivative(const poly &a) {
    if (a.deg == 0)
      return type(0);
    poly f;
    f.set_deg(a.deg);
    cont(i, a.deg) f[i - 1] = a[i] * type(i);
    return f;
  }

  friend inline poly integral(const poly &a) {
    poly f;
    f.set_deg(a.deg);
    circ(i, 0, a.deg - 1) f[i + 1] = a[i] / type(i + 1);
    return f;
  }

  friend inline poly log(const poly &a) {
    poly r;
    r = integral(derivative(a) * inv(a));
    r.set_deg(a.deg);
    return r;
  }

  friend inline poly exp(const poly &a) {
    if (a.deg == 0)
      return type(1);
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = exp(b);

    r.set_deg(a.deg);
    r = r - r * (log(r) - a);

    r.set_deg(a.deg);
    return r;
  }

  friend inline poly pow(const poly &a, int p) {
    int k = 0;
    circ(i, 0, a.deg) if (a[i] != 0) {
      k = i;
      break;
    }
    if (a[k] == 0 || k * p > a.deg)
      return poly(vector<rem>(a.deg + 1, 0));

    poly b;
    b.set_deg(a.deg - k);
    rem rs = inv(a[k]);
    circ(i, 0, a.deg - k) b[i] = a[i + k] * rs;
    rs = pow(a[k], p);

    poly r = exp(p * log(b));
    r.set_deg(a.deg);

    k *= p;
    for (int i = a.deg; i >= k; --i)
      r[i] = r[i - k] * rs;
    loop(i, k) r[i] = 0;
    return r;
  }

  friend inline poly pow(const poly &w, int p, const poly &mod) {
    if (p == 0)
      return poly(1);
    poly a = w, r = poly(1);
    for (; p > 0; a *= a, a %= mod, p >>= 1)
      if (p & 1)
        r *= a, r %= mod;
    return r;
  }

  friend inline ostream &operator<<(ostream &out, const poly &a) {
    out << "{" << a[0];
    cont(i, a.deg) out << ',' << a[i];
    out << "}\\n";
    return out;
  }
};

const int nsz = 1e5;
int n, m, a[nsz + 5], b[nsz + 5];
rem fac[nsz + 5], ifc[nsz + 5], ff[nsz + 5], ans;
poly<rem> f[nsz + 5], g;

void inline transfer() {
  for (int i = 1, cnt = 1; i <= n; ++i, ++cnt) {
    if (a[i] != a[i + 1])
      b[++m] = cnt, cnt = 0;
  }
}

rem inline C(int n, int m) { return fac[n] * ifc[m] * ifc[n - m]; }

void inline factorial_init(int n = nsz) {
  fac[0] = 1;
  cont(i, n) fac[i] = fac[i - 1] * rem(i);
  ifc[n] = inv(fac[n]);
  for (int i = n - 1; i >= 0; --i)
    ifc[i] = ifc[i + 1] * rem(i + 1);
  ff[0] = ff[1] = 1;
  circ(i, 2, n) ff[i] = ff[i - 2] * rem(i);
}

rem inline pair_up(int n, int k) {
  if (n < 2 * k)
    return 0;
  if (k == 0)
    return 1;
  return C(n, 2 * k) * ff[2 * k - 1];
}

poly<rem> solve(int l = 1, int r = m) {
  if (l == r)
    return f[l];
  int md = (l + r) >> 1;
  return solve(l, md) * solve(md + 1, r);
}

bool inline by_deg(const poly<rem> &a, const poly<rem> &b) {
  return a.deg < b.deg;
}

int main() {
  factorial_init();
  scanf("%d", &n);
  n *= 2;
  cont(i, n) scanf("%d", &a[i]);
  sort(a + 1, a + n + 1);
  transfer();
  cont(i, m) {
    vector<rem> cur(1, 1);
    cont(j, b[i] / 2) cur.push_back(pair_up(b[i], j));
    f[i] = cur;
  }
  sort(f + 1, f + m + 1, by_deg);
  g = solve();
  circ(k, 0, g.deg) {
    rem val = g[k] * pair_up(n - 2 * k, n / 2 - k);
    ans += rem(k & 1 ? -1 : +1, 1) * val;
  }
  printf("%d\\n", ans.w);
}

Error: -11

Fixed submission:

#include <bits/stdc++.h>

#define ln '\\n'
#define all(dat) dat.begin(), dat.end()
#define loop(i, to) for (int i = 0; i < to; ++i)
#define cont(i, to) for (int i = 1; i <= to; ++i)
#define circ(i, fm, to) for (int i = fm; i <= to; ++i)
#define foreach(i, dat)                                                        \\
  for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long num;

using namespace std;

template <int mod> struct modulo;
template <int mod> struct modulo_cplx;

template <int mod> struct modulo_cplx {
  modulo<mod> a, b, i2;

  modulo_cplx() {}
  modulo_cplx(modulo<mod> a, modulo<mod> b, modulo<mod> i2 = 0) {
    this->a = a, this->b = b;
    this->i2 = i2;
  }

  inline modulo_cplx operator*(const modulo_cplx &d) {
    return modulo_cplx(a * d.a + i2 * b * d.b, a * d.b + b * d.a, i2);
  }
  inline modulo_cplx &operator*=(const modulo_cplx &d) {
    return *this = *this * d;
  }

  friend inline modulo_cplx pow(const modulo_cplx &w, int p) {
    if (w.a == 0 && w.b == 0)
      return modulo_cplx(0, 0, w.i2);
    modulo_cplx a = w, r = modulo_cplx(1, 0, w.i2);
    for (; p > 0; a *= a, p >>= 1)
      if (p & 1)
        r *= a;
    return r;
  }
};

template <int mod> struct modulo {
  int w;
  operator int &() { return w; }
  operator int() const { return w; }

  modulo() {}
  modulo(int w, bool f = 0) {
    this->w = w;
    if (f)
      fix();
  }
  void inline fix() {
    if (w >= mod || w < -mod)
      w %= mod;
    if (w < 0)
      w += mod;
  }

  inline modulo operator-() {
    w = mod - w;
    if (w >= mod)
      w -= mod;
    return *this;
  }
  inline modulo operator+(const modulo &b) {
    modulo r = *this;
    return r += b;
  }
  inline modulo operator-(const modulo &b) {
    modulo r = *this;
    return r -= b;
  }
  inline modulo operator*(const modulo &b) {
    modulo r = *this;
    return r *= b;
  }
  inline modulo operator/(const modulo &b) {
    modulo r = *this;
    return r /= b;
  }
  inline modulo &operator+=(const modulo &b) {
    if ((w += b.w) >= mod)
      w -= mod;
    return *this;
  }
  inline modulo &operator-=(const modulo &b) {
    if ((w -= b.w) < 0)
      w += mod;
    return *this;
  }
  inline modulo &operator*=(const modulo &b) {
    w = (num)w * b.w % mod;
    return *this;
  }
  inline modulo &operator/=(const modulo &b) { return *this *= inv(b); }

  friend inline modulo inv(const modulo &w) {
    int a = w, m = mod, u = 0, v = 1, t;
    for (; a != 0; t = m / a, m -= t * a, swap(a, m), u -= t * v, swap(u, v))
      ;
    return modulo(u, 1);
  }

  friend inline modulo pow(const modulo &w, int p) {
    if (!w)
      return 0;
    modulo a = w, r = 1;
    for (; p > 0; a *= a, p >>= 1)
      if (p & 1)
        r *= a;
    return r;
  }

  friend inline modulo sqrt(const modulo &w) {
    int k = (mod - 1) / 2;
    assert(pow(w, k) == 1);
    modulo a = rand() % mod;
    for (; pow(a * a - w, k) != mod - 1; a = rand() % mod)
      ;
    modulo_cplx<mod> t(a, 1, a * a - w);
    modulo r = pow(t, (mod + 1) / 2).a;
    return min(int(r), int(mod - r));
  }
};
const int mod = 998244353, mod_root = 3;
typedef modulo<mod> rem;
typedef unsigned long long u64;

const int degsz = int(4e5);

template <class type> struct fourier_transform;
template <class type> struct poly;

template <class type> struct fourier_transform {
  int k, sz, rev[degsz + 5];
  u64 b[degsz + 5], pw[degsz + 5];

  void inline init(int to) {
    for (sz = 1, k = 0; sz <= to; sz <<= 1, ++k)
      ;
    if (k == 0)
      return;
    loop(i, sz) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
  }

  void inline dft(poly<type> &a, int tp = 1) {
    a.set_deg(sz - 1);
    loop(i, sz) {
      b[i] = a[i];
      if (i > rev[i])
        swap(b[i], b[rev[i]]);
    }
    for (int len = 1; len < sz; len <<= 1) {
      int w0 = pow(rem(mod_root), (mod - 1) / (len << 1));
      if (tp == -1)
        w0 = inv(rem(w0));
      pw[0] = 1;
      cont(i, len - 1) pw[i] = pw[i - 1] * w0 % mod;
      for (int l = 0; l < sz; l += len << 1) {
        u64 *p0 = b + l, *p1 = b + l + len, *w = pw, tmp;
        for (int i = 0; i < len; ++i, ++p0, ++p1, ++w) {
          tmp = *w * *p1 % mod;
          *p1 = *p0 + mod - tmp;
          *p0 += tmp;
        }
      }
    }
    loop(i, sz) a[i] = b[i] % mod;
    if (tp == -1) {
      rem rs = inv(rem(sz));
      loop(i, sz) a[i] *= rs;
    }
  }
};
fourier_transform<rem> ft;

template <class type> struct poly {
  int deg;
  vector<type> d;

  poly() { deg = 0; }
  poly(type a) { deg = 0, d.push_back(a); }
  poly(vector<type> a) { deg = int(a.size()) - 1, d = a; }

  void inline set_deg(int sz) { deg = sz, d.resize(sz + 1, 0); }

  void inline fix() {
    for (; d.size() && d.back() == 0; d.pop_back(), --deg)
      ;
  }

  inline type &operator[](int id) { return d[id]; }
  inline type operator[](int id) const { return d[id]; }

  inline type operator()(int x) const {
    if (x == 0)
      return d[0];
    int r = 0;
    for (int i = deg; i >= 0; --i)
      r *= x, r += d[i];
    return r;
  }

  friend inline poly operator+(const poly &a, const poly &b) {
    poly r;
    r.set_deg(max(a.deg, b.deg));
    circ(i, 0, r.deg) r[i] =
        (i <= a.deg ? a[i] : type(0)) + (i <= b.deg ? b[i] : type(0));
    return r;
  }
  friend inline poly operator+(const poly &a, const type &b) {
    poly r = a;
    r[0] += b;
    return r;
  }
  friend inline poly operator+(const type &a, const poly &b) { return b + a; }
  friend inline poly operator+=(poly &a, const poly &b) { return a = a + b; }
  friend inline poly operator+=(poly &a, const type &b) { return a = a + b; }

  friend inline poly operator-(const poly &a, const poly &b) {
    poly r;
    r.set_deg(max(a.deg, b.deg));
    circ(i, 0, r.deg) r[i] =
        (i <= a.deg ? a[i] : type(0)) - (i <= b.deg ? b[i] : type(0));
    return r;
  }
  friend inline poly operator-(const poly &a, const type &b) {
    poly r = a;
    r[0] -= b;
    return r;
  }
  friend inline poly operator-(const type &a, const poly &b) {
    poly r = b - a;
    circ(i, 0, r.deg) r[i] = -r[i];
    return r;
  }
  friend inline poly operator-=(poly &a, const poly &b) { return a = a - b; }
  friend inline poly operator-=(poly &a, const type &b) { return a = a - b; }

  friend inline poly operator*(const poly &a, const poly &b) {
    poly f = a, g = b;
    ft.init(a.deg + b.deg);
    ft.dft(f), ft.dft(g);
    loop(i, ft.sz) f[i] *= g[i];
    ft.dft(f, -1);
    f.set_deg(a.deg + b.deg);
    return f;
  }
  friend inline poly operator*(const poly &a, const type &b) {
    poly r = a;
    circ(i, 0, r.deg) r[i] *= b;
    return r;
  }
  friend inline poly operator*(const type &a, const poly &b) { return b * a; }
  friend inline poly operator*=(poly &a, const poly &b) { return a = a * b; }
  friend inline poly operator*=(poly &a, const type &b) { return a = a * b; }

  friend inline poly operator/(const poly &a, const poly &b) {
    int sz = a.deg - b.deg;
    poly f = a, g = b;
    if (a.deg < b.deg)
      return poly(0);
    reverse(all(f.d)), reverse(all(g.d));
    f.set_deg(sz), g.set_deg(sz);
    f *= inv(g);
    f.set_deg(sz);
    reverse(all(f.d));
    return f;
  }
  friend inline poly operator/=(poly &a, const poly &b) { return a = a / b; }

  friend inline poly operator%(const poly &a, const poly &b) {
    poly r = a - b * (a / b);
    r.set_deg(b.deg - 1);
    return r;
  }
  friend inline poly operator%=(poly &a, const poly &b) { return a = a % b; }

  friend poly inv(const poly &a) {
    if (a.deg == 0)
      return inv(a[0]);
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = inv(b);

    b = a;
    ft.init(2 * a.deg);
    ft.dft(b), ft.dft(r);
    loop(i, ft.sz) r[i] *= (type(2) - r[i] * b[i]);
    ft.dft(r, -1);

    r.set_deg(a.deg);
    return r;
  }

  friend poly sqrt(const poly &a) {
    if (a.deg == 0)
      return sqrt(type(a[0]));
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = sqrt(b);

    r.set_deg(a.deg);
    r = (r + a * inv(r)) * inv(type(2));

    r.set_deg(a.deg);
    return r;
  }

  friend inline poly derivative(const poly &a) {
    if (a.deg == 0)
      return type(0);
    poly f;
    f.set_deg(a.deg);
    cont(i, a.deg) f[i - 1] = a[i] * type(i);
    return f;
  }

  friend inline poly integral(const poly &a) {
    poly f;
    f.set_deg(a.deg);
    circ(i, 0, a.deg - 1) f[i + 1] = a[i] / type(i + 1);
    return f;
  }

  friend inline poly log(const poly &a) {
    poly r;
    r = integral(derivative(a) * inv(a));
    r.set_deg(a.deg);
    return r;
  }

  friend inline poly exp(const poly &a) {
    if (a.deg == 0)
      return type(1);
    int to = a.deg / 2;
    poly b, r;
    b.deg = to, b.d.assign(&a.d[0], &a.d[to + 2]);
    r = exp(b);

    r.set_deg(a.deg);
    r = r - r * (log(r) - a);

    r.set_deg(a.deg);
    return r;
  }

  friend inline poly pow(const poly &a, int p) {
    int k = 0;
    circ(i, 0, a.deg) if (a[i] != 0) {
      k = i;
      break;
    }
    if (a[k] == 0 || k * p > a.deg)
      return poly(vector<rem>(a.deg + 1, 0));

    poly b;
    b.set_deg(a.deg - k);
    rem rs = inv(a[k]);
    circ(i, 0, a.deg - k) b[i] = a[i + k] * rs;
    rs = pow(a[k], p);

    poly r = exp(p * log(b));
    r.set_deg(a.deg);

    k *= p;
    for (int i = a.deg; i >= k; --i)
      r[i] = r[i - k] * rs;
    loop(i, k) r[i] = 0;
    return r;
  }

  friend inline poly pow(const poly &w, int p, const poly &mod) {
    if (p == 0)
      return poly(1);
    poly a = w, r = poly(1);
    for (; p > 0; a *= a, a %= mod, p >>= 1)
      if (p & 1)
        r *= a, r %= mod;
    return r;
  }

  friend inline ostream &operator<<(ostream &out, const poly &a) {
    out << "{" << a[0];
    cont(i, a.deg) out << ',' << a[i];
    out << "}\\n";
    return out;
  }
};

const int nsz = 5e3;
int n, m, a[nsz + 5], b[nsz + 5];
rem fac[nsz + 5], ifc[nsz + 5], ff[nsz + 5], dp[nsz + 5][nsz + 5], ans;
poly<rem> f[nsz + 5], g;

void inline transfer() {
  for (int i = 1, cnt = 1; i <= n; ++i, ++cnt) {
    if (a[i] != a[i + 1])
      b[++m] = cnt, cnt = 0;
  }
}

rem inline C(int n, int m) { return fac[n] * ifc[m] * ifc[n - m]; }

void inline factorial_init(int n = nsz) {
  fac[0] = 1;
  cont(i, n) fac[i] = fac[i - 1] * rem(i);
  ifc[n] = inv(fac[n]);
  for (int i = n - 1; i >= 0; --i)
    ifc[i] = ifc[i + 1] * rem(i + 1);
  ff[0] = ff[1] = 1;
  circ(i, 2, n) ff[i] = ff[i - 2] * rem(i);
}

rem inline pair_up(int n, int k) {
  if (n < 2 * k)
    return 0;
  if (k == 0)
    return 1;
  return C(n, 2 * k) * ff[2 * k - 1];
}

poly<rem> solve(int l = 1, int r = m) {
  if (l == r)
    return f[l];
  int md = (l + r) >> 1;
  return solve(l, md) * solve(md + 1, r);
}

bool inline by_deg(const poly<rem> &a, const poly<rem> &b) {
  return a.deg < b.deg;
}

int main() {
  factorial_init();
  scanf("%d", &n);
  n *= 2;
  cont(i, n) scanf("%d", &a[i]);
  sort(a + 1, a + n + 1);
  transfer();
  cont(i, m) {
    vector<rem> cur(1, 1);
    cont(j, b[i] / 2) cur.push_back(pair_up(b[i], j));
    f[i] = cur;
  }
  sort(f + 1, f + m + 1, by_deg);
  g = solve();
  circ(k, 0, g.deg) {
    rem val = g[k] * pair_up(n - 2 * k, n / 2 - k);
    ans += rem(k & 1 ? -1 : +1) * val;
  }
  printf("%d\\n", ans.w);
}