#include <bits/stdc++.h>
#include <atcoder/convolution>
using namespace atcoder;

typedef long long ll;
const int MAXC = 1e5 + 19, MOD = 998244353;

int qpow(int a, int b){
	int res = 1;
	while(b){
		if(b & 1) res = (ll)res * a % MOD;
		a = (ll)a * a % MOD, b >>= 1;
	}
	return res;
}

int n, t[MAXC];
std::vector<int> r[MAXC];

int fact[MAXC];
int binom(int n, int m){
	return (ll)fact[n] * qpow((ll)fact[n - m] * fact[m] % MOD, MOD - 2) % MOD;
}
int pair_count(int n){
	return (ll)binom(n * 2, n) * fact[n] % MOD * qpow(qpow(2, n), MOD - 2) % MOD;
}

struct Node{
	int x;
	bool operator>(const Node &b)const{return r[x].size() > r[b.x].size();}
};
std::priority_queue<Node, std::vector<Node>, std::greater<Node> > q;

int main(){
	std::scanf("%d", &n);
	for(int i = 1; i <= n * 2; ++i){
		int z; std::scanf("%d", &z);
		++t[z];
	}
	fact[0] = 1;
	for(int i = 1; i <= 100000; ++i)
		fact[i] = (ll)fact[i - 1] * i % MOD;
	for(int i = 1; i <= 100000; ++i)
		if(t[i] >= 1){
			r[i] = {1};
			for(int j = 2; j <= t[i]; j += 2)
				r[i].push_back(binom(t[i], j));
			q.push((Node){i});
		}
	while(q.size() > 1){
		int a = q.top().x; q.pop();
		int b = q.top().x; q.pop();
		r[a] = convolution(r[a], r[b]);
		std::vector<int>().swap(r[b]);
		q.push((Node){a});
	}
	std::vector<int> res(r[q.top().x]);
	int ans = 0;
	for(int i = 0; i < res.size(); ++i){
		if(i > n) break;
		res[i] = (ll)res[i] * pair_count(n - i) % MOD;
		if(i & 1) ans = (ans - res[i]) % MOD;
		else ans = (ans + res[i]) % MOD;
	}
	std::printf("%d\n", (ans + MOD) % MOD);
}