#include <bits/stdc++.h>
#define F first
#define S second
using namespace std;
const int MOD = 998244353;
const int mod = MOD;
typedef long long ll;
typedef long long LL;
const int maxn = 2e5 + 5;
ll pre[maxn], inv[maxn], prei[maxn];
void build(int n){
  pre[1]=pre[0]=inv[1]=inv[0]=prei[1]=prei[0]=1;
  for (int i = 2 ; i <= n ; i++) {
    pre[i] = pre[i-1] * i % mod;
    inv[i] = (mod - mod / i * inv[mod % i] % mod)%mod;
    prei[i] = prei[i-1] * inv[i] % mod;
  }
}
ll PP(int n, int k) {
  return pre[n] * prei[n - k] % mod;
}
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);
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);
    build(maxn - 1);
    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] = 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';
    LL ans = 0;
    for (int i = 0 ; i <= n / 2 ; i++) {
//        cout << i << ": " << res[i] * pre[n - 2 * i] % MOD * fpow(fpow(2, n / 2 - i, MOD), MOD - 2, MOD) % MOD * prei[n / 2 - i] % MOD << '\n';
//        cout << "!: " << pre[n - 2 * i] << '\n';
//        cout << "/2**k: " << fpow(fpow(2, n / 2 - i, MOD), MOD - 2, MOD) << '\n';
//        cout << "/n!: " << prei[n / 2 - i] << '\n';
        if (i % 2 == 0) {
            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;
        } else {
            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: 53376