/**
 *    author:  otera    
**/
#include<iostream>
#include<string> 
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm> 
#include<functional>
#include<iomanip>
#include<queue>
#include<deque>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
using namespace std;

#define int long long
typedef long long ll;
typedef unsigned long long ul;
typedef unsigned int ui;
typedef long double ld;
const int inf=1e9+7;
const ll INF=1LL<<60 ;
const ll mod=1e9+7 ;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef complex<ld> Point;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<int, int> P;
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
#define pb push_back
#define debug(x)  cerr << #x << " = " << (x) << endl;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// #include<atcoder/all>
using namespace std;

// namespace ac = atcoder;

long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

long long modinv(long long a, long long mod) {
    long long b = mod, u = 1, v = 0;
    while (b) {
        long long t = a/b;
        a -= t*b; swap(a, b);
        u -= t*v; swap(u, v);
    }
    u %= mod;
    if (u < 0) u += mod;
    return u;
}

template<const int md>
struct ntt{
	inline void add(int &a, int b) { a += b; if(a >= md) a -= md; }
	inline void sub(int &a, int b) { a -= b; if(a < 0) a += md; }
	inline int mul(int a, int b) { return (int)((ll)a*b%md); }
	inline int power(int a, long long b) {
		int res = 1;
		while (b > 0) {
			if (b & 1) res = mul(res, a);
	    	a = mul(a, a);
			b >>= 1;
		}
		return res;
	}
	inline int inv(int a) {
		a %= md;
		if (a < 0) a += md;
		int b = md, u = 0, v = 1;
		while (a) {
			int t = b / a;
			b -= t * a; swap(a, b);
			u -= t * v; swap(u, v);
		}
		assert(b == 1);
		if (u < 0) u += md;
		return u;
	}
	
 	int max_base, root;
	vector<int> dw, idw;
	ntt() {
		int tmp = md - 1;
		max_base = 0;
		while (tmp % 2 == 0) {
			tmp /= 2;
			max_base++;
		}
		root = 2;
		while (power(root, (md-1)>>1) == 1) root++;
		dw.resize(max_base); idw.resize(max_base);
		rep(i, max_base){
			sub(dw[i], power(root, (md-1) >> (i+2)));
			idw[i] = inv(dw[i]);
		}
	}
	void fft(vector<int> &a, bool inv) {
		const int n = a.size();
		assert((n & (n - 1)) == 0);
		assert(__builtin_ctz(n) <= max_base);
		if(!inv){
			for(int m=n;m>>=1;){
				int w = 1;
				for(int s=0,k=0; s<n; s += 2*m){
					for(int i=s, j=s+m ; i < s+m; ++i, ++j) {
						int x = a[i], y = mul(a[j], w);
						a[j] = (x>=y?x-y:x+md-y);
						a[i] = (x+y>=md?x+y-md:x+y);
					}
					w = mul(w, dw[__builtin_ctz(++k)]);
				}
			}
		}
		else{
			for(int m=1;m<n;m*=2){
				int w = 1;
				for(int s=0,k=0; s<n; s += 2*m){
					for(int i=s, j=s+m ; i < s+m; ++i, ++j) {
						int x = a[i], y = a[j];
						a[j] = (x>=y?x-y:x+md-y);
						a[j] = mul(a[j], w);
						a[i] = (x+y>=md?x+y-md:x+y);
					}
					w = mul(w, idw[__builtin_ctz(++k)]);
				}
			}
		}
	}
	vector<int> multiply(vector<int> a, vector<int> b, int eq = 0) {
		int need = a.size() + b.size() - 1;
		int nbase = 0;
		while ((1 << nbase) < need) nbase++;
		int sz = 1 << nbase;
		a.resize(sz);
		b.resize(sz);
		fft(a, 0);
		if (eq) b = a; else fft(b, 0);
		int inv_sz = inv(sz);
		for (int i = 0; i < sz; i++) {
			a[i] = mul(mul(a[i], b[i]), inv_sz);
		}
		fft(a, 1);
		a.resize(need);
		return a;
	}
	vector<int> square(vector<int> a) {
		return multiply(a, a, 1);
	}
};

const int MOD = 998244353;
ntt<MOD> NTT;

int n;
vector<int> h;

ll fact[200200];
ll finv[200200];

ll com(ll n, ll k) {
    if (n < k || n < 0 || k < 0) return 0;
    return (fact[n] * finv[k] % MOD) * finv[n - k] % MOD;
}

void solve() {
    fact[0] = 1;
    for(int i = 1; i < 200200; ++ i) {
        fact[i] = fact[i - 1] * i % MOD;
    }
    finv[0] = 1;
    for(int i = 1; i < 200200; ++ i) {
        finv[i] = finv[i - 1] * modinv(i, MOD) % MOD;
    }
	cin >> n;
    h.resize(2 * n);
    rep(i, 2 * n) {
        cin >> h[i];
    }
    sort(all(h));
    static int cnt[100100];
    rep(i, 100100) cnt[i] = 0;
    rep(i, 2 * n) {
        cnt[h[i]] ++;
    }
    static int co[100100];
    rep(i, 100100) co[i] = 0;
    rep(i, 100100) {
        co[cnt[i]] ++;
    }
    static ll cc[200200];
    rep(i, 200200) cc[i] = 0;
    cc[0] = 1;
    for(int i = 2; i <= 2 * n; i += 2) {
        cc[i] = cc[i - 2] * com(i, 2) % MOD;
    }
    ll ans = cc[2 * n] * finv[n] % MOD;
    vector<int> dp(1, 0);
    dp[0] = 1;
    for(int i = 2; i <= 2 * n; ++ i) {
        if(co[i] == 0) continue;
        int k = i / 2;
		vector<ll> v(k + 1);
		v[0] = 1LL;
        for(int j = 1; j <= k; ++ j) {
            v[j] = v[j - 1] * fact[j - 1] % MOD * com(i + 2 - j * 2, 2) % MOD * finv[j] % MOD;
        }
		if(co[i] == 1) {
			dp = NTT.multiply(dp, v);
			continue;
		}
		vector<ll> u(1, 1);
		while(co[i] > 0) {
			if(co[i] & 1) u = NTT.multiply(u, v);
			v = NTT.multiply(v, v);
			co[i] >>= 1;
		}
		dp = NTT.multiply(dp, u);
    }
	// cerr << dp[0] << " " << dp[1] << " " << dp[2] << endl;
	// cerr << ans << endl;
    for(int i = 1; i <= min(n, (ll)dp.size() - 1); ++ i) {
        if(i % 2 == 1) {
            ans = ans + MOD - dp[i] * cc[2 * n - 2 * i] % MOD * finv[n - i] % MOD;
            ans %= MOD;
        } else {
            ans = ans + dp[i] * cc[2 * n - 2 * i] % MOD * finv[n - i] % MOD;
            ans %= MOD;
        }
    }
    cout << ans % MOD << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//int t; cin >> t; rep(i, t)solve();
	solve();
    return 0;
}

Measured memory_bytes: 12592