#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
typedef long long LL;
namespace Math {
  const int MOD107 = 1e9 + 7;
  const int MOD998 = 998244353;
  const int INT_INF = 0x3f3f3f3f;
  const LL LL_INF = ((LL)INT_INF << 32) | INT_INF;
  struct Value { virtual ~Value() = default; };
  template <const int P> struct Mint : Value { int v;
    inline int trim(int _v) { return (_v % P + P) % P; }
    Mint (int _v = 0) : v(trim(_v)) { }
    bool operator == (const Mint &m) const { return v == m.v; }
    bool operator != (const Mint &m) const { return v != m.v; }
    bool operator < (const Mint &m) const { return v < m.v; }
    bool operator <= (const Mint &m) const { return v <= m.v; }
    bool operator > (const Mint &m) const { return v > m.v; }
    bool operator >= (const Mint &m) const { return v >= m.v; }
    friend bool operator == (const int &a, const Mint &m) { return Mint(a) == m.v; }
    friend bool operator != (const int &a, const Mint &m) { return Mint(a) != m.v; }
    friend bool operator < (const int &a, const Mint &m) { return Mint(a) < m.v; }
    friend bool operator <= (const int &a, const Mint &m) { return Mint(a) <= m.v; }
    friend bool operator > (const int &a, const Mint &m) { return Mint(a) > m.v; }
    friend bool operator >= (const int &a, const Mint &m) { return Mint(a) >= m.v; }
    Mint& operator += (const Mint &m) { v = trim(v + m.v); return *this; }
    Mint operator + (const Mint &m) const { Mint t = *this; return t += m; }
    friend Mint operator + (const int &a, const Mint &m) { return Mint(a) + m; }
    Mint& operator ++()  { return *this += 1; }
    Mint operator ++(int) { Mint t = *this; ++*this; return t; }
    Mint operator - () const { return Mint(-v); }
    Mint& operator -= (const Mint &m) { v = trim(v - m.v); return *this; }
    Mint operator - (const Mint &m) const { Mint t = *this; return t -= m; }
    friend Mint operator - (const int &a, const Mint &m) { return Mint(a) - m; }
    Mint& operator --()  { return *this -= 1; }
    Mint operator --(int) { Mint t = *this; --*this; return t; }
    Mint& operator *= (const Mint &m) { v = trim(1ll * v * m.v % P); return *this; }
    Mint operator * (const Mint &m) const { Mint t = *this; return t *= m; }
    friend Mint operator * (const int &a, const Mint &m) { return Mint(a) * m; }
    Mint pow(long long n) const { Mint m = *this, ans = 1; while (n) ans *= (n & 1 ? m : 1), m *= m, n >>= 1; return ans; }
    Mint pow(const Mint &n) const { return pow(n.v); }
    Mint inv() const { return pow(P - 2); }
    Mint& operator /= (const Mint &m) { *this = v * m.inv(); return *this; }
    Mint operator / (const Mint &m) { Mint t = *this; return t /= m; }
    friend Mint operator / (const int &a, const Mint &m) { return Mint(a) / m; }
    friend istream& operator >> (istream &in, Mint &m) { int v; in >> v; m = Mint(v); return in; }
    friend ostream& operator << (ostream &out, const Mint &m) { out << m.v; return out; }
  };
  template <typename T> T add(T a, T b) { return a + b; }
  template <typename T> T max(T a, T b) { return a < b ? b : a; }
  template <typename T> T min(T a, T b) { return a < b ? a : b; }
  unordered_map<int, vector<Value*>> fact_mp, inv_mp, fact_inv_mp;
  template <const int P> void _build(int n);
  template <const int P> Mint<P> fact(int n) {
    assert(0 <= n); _build<P>(n);
    auto &_fact = fact_mp[P];
    return *dynamic_cast<Mint<P>*>(_fact[n]);
  }
  template <const int P> Mint<P> fact_inv(int n) {
    assert(0 <= n); _build<P>(n);
    auto &_fact_inv = fact_inv_mp[P];
    return *dynamic_cast<Mint<P>*>(_fact_inv[n]);
  }
  template <const int P> Mint<P> C(int n, int m) {
    assert(0 <= n && m >= 0 && m <= n); _build<P>(n);
    return fact<P>(n) * fact_inv<P>(m) * fact_inv<P>(n - m);
  }
  template <const int P> Mint<P> inv(int n) {
    assert(0 <= n); _build<P>(n);
    auto &_inv = inv_mp[P];
    return *dynamic_cast<Mint<P>*>(_inv[n]);
  }
  template <const int P> void _build(int n) {
    auto &_fact = fact_mp[P];
    auto &_inv = inv_mp[P];
    auto &_fact_inv = fact_inv_mp[P];
    while (_fact.size() <= n) {
      if ((int)_fact.size() <= 1) {
        _fact.push_back(new Mint<P>(1));
        _inv.push_back(new Mint<P>(1));
        _fact_inv.push_back(new Mint<P>(1));
        continue;
      }
      int x = _fact.size();
      _fact.push_back(new Mint<P>(fact<P>(x - 1) * x));
      _inv.push_back(new Mint<P>(-inv<P>(P % x) * Mint<P>(P / x)));
      _fact_inv.push_back(new Mint<P>(fact_inv<P>(x - 1) * inv<P>(x)));
    }
  }
}
namespace DS {
  template <typename T, T e, T (*F)(T, T)> struct BIT {
    vector<T> data; int n;
    BIT (int _n = 0) { init(_n); }
    BIT (vector<T> arr) { init(arr); }
    void init(int _n) { n = _n; data.assign(n + 1, e); }
    void init(vector<T> arr) { init(arr.size());
      for (int i = 0 ; i < arr.size() ; i++) m(i, arr[i]);
    }
    T q(int R) { assert(0 <= R && R <= n);
      T ret = e;
      while (R > 0)
        ret = F(ret, data[R]), R -= R & -R;
      return ret;
    }
    void m(int x, T d) { x++;
      while (x <= n)
        data[x] = F(data[x], d), x += x & -x;
    }
    friend ostream& operator << (ostream& out, BIT &bit) {
      out << "===========================================\n";
      cout << "structure type: BIT, size: " << bit.n << '\n';
      for (int i = 0 ; i <= bit.n ; i++)
        cout << "bit[0, " << i << "): " << bit.q(i) << '\n';
      out << "===========================================\n";
      return out;
    }
    friend istream& operator >> (istream& in, BIT &bit) {
      vector<T> arr(bit.n);
      for (auto &v : arr) in >> v;
      bit.init(arr);
      return in;
    }
  };
  template <typename T, T (*F)(T, T)> struct SparseTable {
    int n, lgn; vector<vector<T>> data;
    SparseTable(int _n) { vector<T> arr(n = _n); init(arr); }
    SparseTable(vector<T> arr) { init(arr); }
    void init(vector<T> arr) { n = arr.size();
      data.assign(lgn = __lg(n) + 1, vector<T>(n));
      data[0] = arr;
      for (int h = 0 ; h < lgn - 1 ; h++) {
        for (int i = 0 ; i < n ; i++) {
          if (i + (1 << h) < n)
            data[h + 1][i] = F(data[h][i], data[h][i + (1 << h)]);
          else
            data[h + 1][i] = data[h][i];
        }
      }
    }
    T q(int L, int R) {
      assert(0 <= L && L < n && 0 < R && R <= n && L < R);
      T ret = data[0][L];
      for (int h = lgn - 1 ; h >= 0 ; h--)
        if (L + (1 << h) <= R)
          ret = F(ret, data[h][L]), L += 1 << h;
      return ret;
    }
    friend istream& operator >> (istream &in, SparseTable &st) {
      vector<T> arr(st.n);
      for (auto &v : arr) in >> v;
      st.init(arr);
      return in;
    }
    friend ostream& operator << (ostream &out, SparseTable &st) {
      out << "===========================================\n";
      out << "structure type: SparseTable, size: " << st.n << '\n';
      for (int i = 0 ; i < st.n ; i++)
        for (int j = i + 1 ; j <= st.n ; j++)
          cout << "[" << i << ", " << j << "): " << st.q(i, j) << '\n';
      out << "===========================================\n";
      return out;
    }
  };
}
namespace IO {
}
namespace Graph {
}
namespace Geometry {
}
namespace String {
}

using namespace Math;
#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
int fpow(int a, int n, int P) {
  int r = 1; while (n) {
    if (n & 1)
      r = 1ll * r * a % P;
    a = 1ll * a * a % P; n >>= 1;
  }
  return r;
}
const int P = 998244353, R = 3, MAXN = (1 << 23);
const int MOD = MOD998;
struct Poly : vector<int> { int n;
  Poly (int n) : n(n) { this->resize(n); }
  int extend(int x) {
    int N = 1; while (N < x) N <<= 1; return N;
  }
  Poly operator * (const Poly &rhs) {
    Poly a = *this, b = rhs;
    int N = extend(n + rhs.n - 1);
    a.resize(a.n = N); a.ntt(1);
    b.resize(b.n = N); b.ntt(1);
    for (int i = 0 ; i < N ; i++)
      a[i] = 1ll * a[i] * b[i] % P;
    return a.ntt(-1), a.n = n + rhs.n, a;
  }
  void ntt(int op) { static Poly r(MAXN);
    for (int i = 0 ; i < n ; i++) {
      r[i] = (i & 1) * (n >> 1) + (r[i >> 1] >> 1);
      if (r[i] < i) std::swap(at(i), at(r[i]));
    }
    for (int m = 2 ; m <= n ; m <<= 1) {
      int k = m >> 1, gn = fpow(R, (P - 1) / m, P);
      for (int i = 0 ; i < n ; i += m) { int g = 1;
        for (int j = 0 ; j < k ; j++, g = 1ll * g * gn % P) {
          int tmp = 1ll * at(i + j + k) * g % P;
          at(i + j + k) = (at(i + j) - tmp + P) % P;
          at(i + j) = (at(i + j) + tmp) % P;
        }
      }
    }
    if (op == -1) {
      reverse(begin() + 1, end());
      int inv = fpow(n, P - 2, P);
      for (int i = 0 ; i < n ; i++)
        at(i) = 1ll * at(i) * inv % P;
    }
  }
  bool operator < (const Poly &rhs) const {
    return n > rhs.n;
  }
};
typedef pair<int, int> pii;
int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);
    int n; cin >> n;
    map<int, int> cnt;
    for (int i = 0 ; i < 2 * n ; i++) {
        int v; cin >> v;
        cnt[v]++;
    }
    n *= 2;
    priority_queue<Poly> pq;
    for (auto &p : cnt) {
        int k = p.S / 2;
        Poly poly(k + 1);
        for (int i = 0 ; i <= k ; i++) {
            poly[i] = (C<MOD>(p.S, 2 * i) * fact<MOD>(2 * i) * fact_inv<MOD>(i) / Mint<MOD>(2).pow(i)).v;
//            poly[i] = PP(p.S, 2 * i) * fpow(fpow(2, i, MOD), MOD - 2, MOD) % MOD * prei[i] % MOD;
        }
//        cout << p.F << ' ' << p.S << ": ";
//        for (int i = 0 ; i <= k ; i++)
//            cout << poly[i] << ' ';
//        cout << '\n';
        pq.push(poly);
    }
    while (pq.size() > 1) {
        auto a = pq.top(); pq.pop();
        auto b = pq.top(); pq.pop();
        pq.push(a * b);
    }
    auto res = pq.top(); pq.pop();
//    for (int i = 0 ; i < res.n ; i++)
//        cout << res[i] << ' ';
//    cout << '\n';
    Mint<MOD998> ans = 0;
    for (int i = 0 ; i <= n / 2 ; i++) {
        if (i % 2 == 0) {
            ans += res[i] * fact<MOD>(n - 2 * i) / Mint<MOD>(2).pow(n / 2 - i) * fact_inv<MOD>(n / 2 - i);
        } else {
            ans -= res[i] * fact<MOD>(n - 2 * i) / Mint<MOD>(2).pow(n / 2 - i) * fact_inv<MOD>(n / 2 - i);
//            ans -= res[i] * pre[n - 2 * i] % MOD * fpow(fpow(2, n / 2 - i, MOD), MOD - 2, MOD) % MOD * prei[n / 2 - i] % MOD;
//            ans += MOD;
//            ans %= MOD;
        }
    }
    cout << ans << '\n';
}


Measured memory_bytes: 55816