#include <bits/extc++.h>

template <uint32_t Modulus>
struct modular {
  static_assert(int(Modulus) > 0, "Modulus must be in the range [1, 2^31)");
  static constexpr int modulus() { return Modulus; }

  modular() : v(0) {}
  modular(int64_t x) : v(x % Modulus) {
    if (int(v) < 0) v += Modulus;
  }

  explicit operator int() const { return v; }
  modular& operator++() { return ++v == Modulus ? v = 0 : 0, *this; }
  modular& operator--() { return --(v ? v : v = Modulus), *this; }
  modular operator+() const { return *this; }
  modular operator-() const {
    modular res;
    res.v = v ? Modulus - v : 0;
    return res;
  }
  modular& operator*=(modular b) {
    v = uint64_t(v) * b.v % Modulus;
    return *this;
  }
  modular& operator/=(modular b) {
    auto [x, gcd] = extgcd(b.v, Modulus);
    assert(gcd == 1);
    return *this *= x;
  }
  modular& operator+=(modular b) {
    v += b.v - Modulus;
    if (int(v) < 0) v += Modulus;
    return *this;
  }
  modular& operator-=(modular b) {
    v -= b.v;
    if (int(v) < 0) v += Modulus;
    return *this;
  }

  friend modular operator++(modular& a, int) {
    return std::exchange(a, ++modular(a));
  }
  friend modular operator--(modular& a, int) {
    return std::exchange(a, --modular(a));
  }
  friend modular operator*(modular a, modular b) { return a *= b; }
  friend modular operator/(modular a, modular b) { return a /= b; }
  friend modular operator+(modular a, modular b) { return a += b; }
  friend modular operator-(modular a, modular b) { return a -= b; }
  friend std::istream& operator>>(std::istream& is, modular& b) {
    int64_t x;
    return is >> x, b = x, is;
  }
  friend std::ostream& operator<<(std::ostream& os, modular b) {
    return os << b.v;
  }
  friend bool operator==(modular a, modular b) { return a.v == b.v; }
  friend bool operator!=(modular a, modular b) { return a.v != b.v; }

 private:
  static std::pair<int, int> extgcd(int a, int b) {
    std::array x{1, 0};
    while (b) {
      int q = a / b;
      std::swap(x[0] -= q * x[1], x[1]);
      std::swap(a -= q * b, b);
    }
    return {x[0], a};
  }

  uint32_t v;
};

template <class T, class U, class BinaryOperation = std::multiplies<>>
constexpr T power(T a, U n, T init = 1,
                  BinaryOperation binary_op = BinaryOperation{}) {
  static_assert(std::is_integral_v<U> and not std::is_same_v<U, bool>);
  assert(n >= 0);
  while (n) {
    if (n & 1) init = binary_op(init, a);
    if (n >>= 1) a = binary_op(a, a);
  }
  return init;
}

template <class T>
void ntt(std::vector<T>& a, bool inverse) {
  int n = size(a);
  assert((n & (n - 1)) == 0);
  if (n < 2) return;
  assert((T::modulus() - 1) % n == 0);
  static std::vector<T> w{1}, iw{1};
  for (int m = size(w); m < n / 2; m *= 2) {
    static T root = 2;
    while (power(root, (T::modulus() - 1) / 2) == 1) ++root;
    T dw = power(root, (T::modulus() - 1) / (4 * m)), idw = 1 / dw;
    w.resize(2 * m), iw.resize(2 * m);
    for (int i = 0; i < m; ++i) w[m + i] = w[i] * dw, iw[m + i] = iw[i] * idw;
  }
  if (not inverse) {
    for (int m = n; m >>= 1;) {
      for (int s = 0, k = 0; s < n; s += 2 * m, ++k) {
        for (int i = s, j = s + m; i < s + m; ++i, ++j) {
          T x = a[i], y = a[j] * w[k];
          a[i] = x + y, a[j] = x - y;
        }
      }
    }
  } else {
    for (int m = 1; m < n; m *= 2) {
      for (int s = 0, k = 0; s < n; s += 2 * m, ++k) {
        for (int i = s, j = s + m; i < s + m; ++i, ++j) {
          T x = a[i], y = a[j];
          a[i] = x + y, a[j] = (x - y) * iw[k];
        }
      }
    }
    auto inv = 1 / T(n);
    for (auto&& e : a) e *= inv;
  }
}
template <class T>
std::vector<T> operator*(std::vector<T> a, std::vector<T> b) {
  if (empty(a) or empty(b)) return {};
  int n = size(a), m = size(b), sz = 1 << std::__lg(2 * (n + m - 1) - 1);
  if (std::min(n, m) < 30) {
    std::vector<T> res(n + m - 1);
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < m; ++j) res[i + j] += a[i] * b[j];
    return res;
  }
  bool eq = a == b;
  a.resize(sz), ntt(a, false);
  if (eq)
    b = a;
  else
    b.resize(sz), ntt(b, false);
  for (int i = 0; i < sz; ++i) a[i] *= b[i];
  ntt(a, true), a.resize(n + m - 1);
  return a;
}

int main() {
  using namespace std;
  cin.tie(nullptr)->sync_with_stdio(false);

  using mint = modular<998244353>;
  constexpr int lim = 1e5;
  vector<mint> fact(lim + 1);
  for (int i = 0; i <= lim; ++i) fact[i] = i ? i * fact[i - 1] : 1;

  int n;
  cin >> n;
  n *= 2;
  map<int, int> mp;
  for (int _ = n; _--;) {
    int h;
    cin >> h;
    ++mp[h];
  }

  using poly = vector<mint>;
  auto comp = [&](const poly& a, const poly& b) { return size(a) > size(b); };
  priority_queue<poly, vector<poly>, decltype(comp)> pq(comp);

  for (auto [h, sz] : mp) {
    vector<mint> t(sz / 2 + 1);
    for (int i = 0; 2 * i <= sz; ++i)
      t[i] = fact[sz] / fact[sz - 2 * i] / power<mint>(2, i) / fact[i];
    pq.push(t);
  }
  while (size(pq) > 1) {
    auto t0 = pq.top();
    pq.pop();
    auto t1 = pq.top();
    pq.pop();
    pq.push(t0 * t1);
  }
  auto f = pq.top();

  mint ans;
  for (int k = 0; k < int(size(f)); ++k) {
    int r = n / 2 - k;
    ans += power(-1, k) * f[k] * fact[2 * r] / power<mint>(2, r) / fact[r];
  }
  cout << ans << '\n';
}


Measured memory_bytes: 13712