#include <bits/stdc++.h>
using namespace std;
inline long long int mpow(long long int a, long long int b,
                          long long int p = -1) {
  long long int ret = 1, num = a;
  while (b > 0) {
    if (b & 1) ret = (ret * num) % p;
    num = (num * num) % p;
    b /= 2;
  }
  return ret;
}
long long int modsqrt(long long int a, long long int mod) {
  a %= mod;
  if (a == 0) return 0LL;
  if (mod == 2) return 1LL;
  if (mpow(a, (mod - 1) / 2, mod) != 1) return -1LL;
  if (mod % 4 == 3) return mpow(a, mod / 4 + 1, mod);
  long long int q = mod - 1, m = 0;
  while (q % 2 == 0) q >>= 1, m++;
  mt19937 mt;
  long long int z;
  do {
    z = mt() % mod;
  } while (mpow(z, (mod - 1) / 2, mod) != mod - 1);
  long long int c = mpow(z, q, mod);
  long long int t = mpow(a, q, mod);
  long long int r = mpow(a, (q + 1) >> 1, mod);
  for (; m > 1; --m) {
    long long int tmp = mpow(t, 1LL << (m - 2), mod);
    if (tmp != 1) r = r * c % mod, t = t * (c * c % mod) % mod;
    c = c * c % mod;
  }
  return r;
}
template <long long int P, long long int proot>
struct NTT {
  long long int g;
  vector<long long int> primes;
  NTT(){};
  long long int get_mod() { return P; }
  void ntt(vector<long long int>& f, bool inv) {
    int n, N = f.size();
    g = mpow(proot, P / N, P);
    vector<long long int> angles(N);
    angles[0] = 1;
    for (int i = 1; i < N; i++) angles[i] = (angles[i - 1] * g) % P;
    for (n = 0;; n++)
      if (N == (1 << n)) break;
    for (int m = 0; m < N; m++) {
      int m2 = 0;
      for (int i = 0; i < n; i++)
        if (m & (1 << i)) m2 |= (1 << (n - 1 - i));
      if (m < m2) swap(f[m], f[m2]);
    }
    for (int i = 0; i < N; i++) f[i] %= P;
    vector<long long int> power(N / 2);
    power[0] = 1;
    for (int t = 1; t < N; t *= 2) {
      long long int w = angles[N / (2 * t)];
      if (inv) w = angles[N - N / (2 * t)];
      for (int i = 1; i < t; i++) power[i] = (power[i - 1] * w) % P;
      for (int i = 0; i < N; i += 2 * t) {
        for (int j = 0; j < t; j++) {
          long long int x = f[i + j], y = f[i + t + j];
          f[i + j] = (x + y * power[j]) % P;
          f[i + t + j] = x - (y * power[j]) % P;
          if (f[i + t + j] < 0) f[i + t + j] += P;
        }
      }
    }
    if (inv) {
      long long int inv = mpow(N, P - 2, P);
      for (int i = 0; i < N; i++) f[i] = (f[i] * inv) % P;
    }
  }
  vector<long long int> conv(vector<long long int> A, vector<long long int> B) {
    assert(A.size() == B.size());
    long long int N = A.size();
    vector<long long int> C(N);
    ntt(A, 0);
    ntt(B, 0);
    for (int i = 0; i < N; i++) C[i] = (A[i] * B[i]) % P;
    ntt(C, 1);
    return C;
  }
};
vector<long long int> int32mod_conv(vector<long long int> a,
                                    vector<long long int> b, long long int P) {
  if (P == 998244353) return NTT<998244353, 3>().conv(a, b);
  NTT<167772161, 3> ntt1;
  NTT<469762049, 3> ntt2;
  NTT<1224736769, 3> ntt3;
  vector<long long int> A = ntt1.conv(a, b);
  vector<long long int> B = ntt2.conv(a, b);
  vector<long long int> C = ntt3.conv(a, b);
  long long int N = A.size();
  vector<long long int> ret(N);
  long long int x = ntt1.get_mod();
  long long int y = ntt2.get_mod();
  long long int z = ntt3.get_mod();
  long long int ix = mpow(x, y - 2, y);
  long long int ixy = mpow((x * y) % z, z - 2, z);
  for (int i = 0; i < N; i++) {
    long long int v = ((B[i] - A[i]) * ix) % y;
    if (v < 0) v += y;
    long long int xxv = A[i] + x * v;
    v = ((C[i] - (xxv % z)) * ixy) % z;
    if (v < 0) v += z;
    ret[i] = ((xxv % P) + ((x * y) % P) * v) % P;
  }
  return ret;
}
template <long long int P>
struct FPS : vector<long long int> {
  using vector<long long int>::vector;
  static vector<long long int> itable;
  FPS(vector<long long int> a) {
    long long int N = 1, n = a.size();
    while (N < n) N *= 2;
    this->resize(n);
    for (int i = 0; i < n; i++) (*this)[i] = a[i];
  }
  FPS operator+(const FPS& r) { return FPS(*this) += r; }
  FPS operator-(const FPS& r) { return FPS(*this) -= r; }
  FPS operator*(const FPS& r) { return FPS(*this) *= r; }
  FPS operator/(const FPS& r) { return FPS(*this) /= r; }
  FPS operator+(const long long int& r) { return FPS(*this) += r; }
  FPS operator-(const long long int& r) { return FPS(*this) -= r; }
  FPS operator*(const long long int& r) { return FPS(*this) *= r; }
  FPS operator/(const long long int& r) { return FPS(*this) /= r; }
  FPS operator+=(const FPS& r) {
    if (r.size() > this->size()) this->resize(r.size());
    for (int i = 0; i < r.size(); i++) {
      (*this)[i] += r[i];
      if ((*this)[i] > P) (*this)[i] -= P;
    }
    return *this;
  }
  FPS operator-=(const FPS& r) {
    if (r.size() > this->size()) this->resize(r.size());
    for (int i = 0; i < r.size(); i++) {
      (*this)[i] -= r[i];
      if ((*this)[i] < 0) (*this)[i] += P;
    }
    return *this;
  }
  FPS operator*=(FPS r) {
    long long int n = max(this->size(), r.size()) * 2, N = 1;
    while (N < n) N *= 2;
    this->resize(N);
    r.resize(N);
    return (*this) = (int32mod_conv(*this, r, P));
  }
  FPS operator/=(FPS r) { return (*this) *= r.inv(); }
  FPS operator+=(const long long int& r) {
    if (this->empty()) this->resize(1);
    (*this)[0] += r;
    if ((*this)[0] > P) (*this)[0] -= P;
    return *this;
  }
  FPS operator-=(const long long int& r) {
    if (this->empty()) this->resize(1);
    (*this)[0] -= r;
    if ((*this)[0] < 0) (*this)[0] += P;
    return *this;
  }
  FPS operator*=(const long long int& r) {
    if (this->empty()) this->resize(1);
    const long long int n = this->size();
    for (int i = 0; i < n; i++) (*this)[i] = ((*this)[i] * r) % P;
    return *this;
  }
  FPS operator/=(const long long int& r) {
    if (this->empty()) this->resize(1);
    long long int inv = mpow(r, P - 2, P);
    const long long int n = this->size();
    for (int i = 0; i < n; i++) (*this)[i] = ((*this)[i] * inv) % P;
    return *this;
  }
  FPS operator>>(int sz) const {
    if (this->size() <= sz) return {};
    FPS ret = *this;
    ret.erase(ret.begin(), ret.begin() + sz);
    return ret;
  }
  FPS operator<<(int sz) const {
    FPS ret = *this;
    ret.insert(ret.begin(), sz, 0);
    return ret;
  }
  FPS prefix(int deg) {
    return FPS(this->begin(), this->begin() + min((int)this->size(), deg));
  }
  FPS inv(int deg = -1) {
    assert((*this)[0] != 0);
    const int n = this->size();
    if (deg == -1) deg = n;
    FPS ret({mpow((*this)[0], P - 2, P)});
    for (int i = 1; i < deg; i <<= 1)
      ret = (ret + ret - ret * ret * prefix(i << 1)).prefix(i << 1);
    return ret.prefix(deg);
  }
  FPS integral() {
    const int n = (int)this->size();
    FPS ret(n + 1);
    ret[0] = 0;
    long long int inv[n + 2];
    inv[0] = inv[1] = 1;
    for (int i = 0; i < n; i++) {
      ret[i + 1] = ((*this)[i] * inv[i + 1]) % P;
      inv[i + 2] = ((-(P / (i + 2)) * inv[P % (i + 2)]) % P + P) % P;
    }
    return ret;
  }
  FPS diff() {
    const int n = (int)this->size();
    FPS ret(max(0, n - 1));
    for (int i = 1; i < n; i++) ret[i - 1] = ((*this)[i] * i) % P;
    return ret;
  }
  FPS log(int deg = -1) {
    assert((*this)[0] == 1);
    const int n = (int)this->size();
    if (deg == -1) deg = n;
    return (this->diff() * this->inv(deg)).prefix(deg - 1).integral();
  }
  FPS exp(int deg = -1) {
    assert((*this)[0] == 0);
    const int n = this->size();
    if (deg == -1) deg = n;
    FPS ret(vector<long long int>{1});
    for (int i = 1; i < deg; i <<= 1) {
      ret = (ret * (prefix(i << 1) + 1LL - ret.log(i << 1))).prefix(i << 1);
    }
    return ret.prefix(deg);
  }
  void print(FPS a) {
    long long int n = a.size();
    for (int i = 0; i < n - 1; i++) printf("%lld ", a[i]);
    printf("%lld\n", a[n - 1]);
  }
  FPS sqrt(int deg = -1) {
    const int n = this->size();
    if (deg == -1) deg = n;
    if ((*this)[0] == 0) {
      for (int i = 1; i < n; i++) {
        if ((*this)[i] != 0) {
          if (i & 1) {
            std::cout << -1 << '\n';
            exit(0);
          }
          if (deg - i / 2 <= 0) break;
          FPS tmp = (*this >> i).sqrt(deg - i / 2);
          if (tmp.size() == 0) return {};
          FPS ret = tmp << (i / 2);
          if (ret.size() < deg) ret.resize(deg, 0);
          return ret;
        }
      }
      return FPS(deg, 0);
    }
    long long int x = modsqrt((*this)[0], P);
    if (x == -1) return {};
    FPS ret({x});
    long long int inv2 = mpow(2, P - 2, P);
    for (int i = 1; i < deg; i <<= 1)
      ret = (ret + this->prefix(i << 1) * ret.inv(i << 1)) * inv2;
    return ret.prefix(deg);
  }
  FPS pow(long long int k, int deg = -1) const {
    const int n = (int)this->size();
    if (deg == -1) deg = n;
    for (long long int i = 0; i < n; i++) {
      if ((*this)[i] != 0) {
        long long int rev = mpow((*this)[i], P - 2, P);
        FPS C = (*this);
        C *= rev;
        FPS D(deg);
        for (long long int j = i; j < n; j++) D[j - i] = C[j];
        D = (D.log(deg) * k).exp(deg) * mpow((*this)[i], k, P);
        FPS E(deg);
        if (i * k > deg) return E;
        auto S = i * k;
        for (long long int j = 0; j + S < deg && j < D.size(); j++)
          E[j + S] = D[j];
        return E;
      }
    }
    return *this;
  }
  long long int Nth_element(long long int N, FPS p, FPS q) {
    if (N <= 20) return (p / q)[N];
    FPS tmp(q.size(), 0);
    for (int i = 0; i < q.size(); i++) tmp[i] = (i % 2 ? (P - q[i]) : q[i]);
    p *= tmp;
    q *= tmp;
    FPS p2(p.size() / 2);
    FPS q2(q.size() / 2);
    if (N % 2)
      for (int i = 1; i < p.size(); i += 2) p2[i / 2] = p[i];
    else
      for (int i = 0; i < p.size(); i += 2) p2[i / 2] = p[i];
    for (int i = 0; i < q.size(); i += 2) q2[i / 2] = q[i];
    return Nth_element(N / 2, p2, q2);
  }
};
long long int fac[300000 + 1], inv[300000 + 1], finv[300000 + 1];
long long int comb(long long int n, long long int k) {
  if (n < 0 || k < 0 || n < k) return 0;
  return (((fac[n] * finv[n - k]) % 998244353) * finv[k]) % 998244353;
}
long long int perm(long long int n, long long int k) {
  if (n < 0 || k < 0 || n < k) return 0;
  return (fac[n] * finv[n - k]) % 998244353;
}
void init() {
  fac[0] = finv[0] = fac[1] = finv[1] = inv[1] = 1;
  for (int i = 2; i <= 300000; i++) {
    fac[i] = (fac[i - 1] * i) % 998244353;
    inv[i] = ((-(998244353 / i) * inv[998244353 % i]) % 998244353 + 998244353) %
             998244353;
    finv[i] = (finv[i - 1] * inv[i]) % 998244353;
  }
}
long long int pp(long long int a, long long int b) {
  return (a * b) % 998244353;
}
long long int mpow(long long int a, long long int b) {
  long long int ret = 1, num = a;
  while (b > 0) {
    if (b & 1) ret = (ret * num) % 998244353;
    num = (num * num) % 998244353;
    b /= 2;
  }
  return ret;
}
vector<long long int> mem(300001, 1);
void ini() {
  for (long long int i = 2; i < 300001; i += 2) {
    mem[i] = (mem[i - 2] * (i - 1)) % 998244353;
  }
}
int main() {
  init();
  ini();
  long long int n;
  std::cin >> n;
  vector<long long int> cnt(100001, 0);
  for (int i = 0; i < 2 * n; i++) {
    long long int a;
    scanf("%lld", &a);
    cnt[a]++;
  }
  multiset<pair<int, FPS<998244353>>> st;
  for (int i = 0; i < 100001; i++) {
    if (cnt[i] == 0) continue;
    FPS<998244353> tmp(cnt[i] / 2 + 1, 0);
    tmp[0] = 1;
    long long int ret = 1;
    for (long long int j = 1; j <= cnt[i] / 2; j++) {
      ret = (ret * comb(cnt[i] - 2 * j + 2, 2));
      tmp[j] = ret;
    }
    st.insert({tmp.size(), tmp});
  }
  st.insert({1, FPS<998244353>{1}});
  while (st.size() > 1) {
    auto L = *st.begin();
    auto R = *(--st.end());
    FPS<998244353> mg = L.second * R.second;
    st.erase(st.begin());
    st.erase(--st.end());
    st.insert({mg.size(), mg});
  }
  FPS<998244353> ans = (*st.begin()).second;
  int k = ans.size();
  long long int A = 1;
  for (long long int i = 2 * n - 1; i >= 1; i -= 2) A = (A * i) % 998244353;
  for (int i = 1; i < k; i++) {
    if (ans[i] == 0) continue;
    long long int x = mem[2 * n - 2 * i];
    if (i % 2)
      A = (A - (ans[i] * x) % 998244353 + 998244353) % 998244353;
    else
      A = (A + (ans[i] * x) % 998244353) % 998244353;
  }
  std::cout << A << '\n';
}
