#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int N = 2e5 + 20 , p = 998244353 , g = 3;
typedef vector<int> Poly;
int h[N];

int wu1[N] , wu2[N];
int rev[N];
int fac[N] , ifac[N];
int r[N];
int d; 
int fpw(int x , int t){
	if(!t) return 1;
	int o = fpw(x , t >> 1);
	o = 1ll * o * o % p;
	if(t & 1) o = 1ll * o * x % p;
	return o;
}
void getrev(int L){ //L = n + m
	d = 1;
	while(d < L)
		d <<= 1;
	int half = (d >> 1);
	for(int i = 1 ; i < d ; ++ i)
		rev[i] = ((rev[i >> 1] >> 1) | (i & 1 ? half : 0));
}
void ntt_core(Poly &a , int* wu){
	for(int i = 0 ; i < d ; ++ i)
		if(rev[i] > i)
			swap(a[i] , a[rev[i]]);
	for(int i = 1 ; i < d ; i <<= 1)
		for(int j = 0 ; j < d ; j += (i << 1))
			for(int k = 0 ; k < i ; k ++){
				int a1 = a[j + k] , a2 = 1ll * a[j + k + i] * wu[i + k] % p;
				a[j + k] = (a1 + a2) % p;
				a[j + k + i] = (a1 + p - a2) % p;
			}
}
void intt(Poly &a , int* wu){
	ntt_core(a , wu);
	int c = fpw(d , p - 2);
	for(int i = 0 ; i < d ; ++ i)
		a[i] = 1ll * a[i] * c % p;
}
void ntt(Poly &a , int* wu){
	ntt_core(a , wu);
}

Poly mul(Poly a , Poly b){
	int L = (int)a.size() + (int)b.size() - 1;
	getrev(L);
	a.resize(d) , ntt(a , wu1);
	b.resize(d) , ntt(b , wu1);
	Poly c(d);
	for(int i = 0 ; i < d ; ++ i)
		c[i] = 1ll * a[i] * b[i] % p;
	intt(c , wu2);
	c.resize(L);
	return c;
}

void init(){
	d = 65536;
	int c = fpw(g , (p - 1) / d) , half = (d >> 1);
	wu1[half] = 1;
	for(int i = half + 1 ; i < d ; ++ i)
		wu1[i] = 1ll * wu1[i - 1] * c % p;
	for(int i = half - 1 ; i ; -- i)
		wu1[i] = wu1[i << 1];
	c = fpw(c , p - 2);
	wu2[half] = 1;
	for(int i = half + 1 ; i < d ; ++ i)
		wu2[i] = 1ll * wu2[i - 1] * c % p;
	for(int i = half - 1 ; i ; -- i)
		wu2[i] = wu2[i << 1];
	r[0] = 1; r[1] = 1;
	for(int i = 2 ; i <= (d << 1) ; i += 2){
		r[i] = 1ll * (i - 1) * r[i - 2] % p;
		r[i + 1] = 1ll * (i + 1) * r[i] % p;
	}
	fac[0] = fac[1] = 1;
	for(int i = 2 ; i <= (d << 1) ; ++ i)
		fac[i] = 1ll * fac[i - 1] * i % p;
	ifac[0] = ifac[1] = 1;
	for(int i = 2 ; i <= (d << 1) ; ++ i)
		ifac[i] = p - 1ll * (p / i) * ifac[p % i] % p;
	for(int i = 2 ; i <= (d << 1) ; ++ i)
		ifac[i] = 1ll * ifac[i - 1] * ifac[i] % p;
}

int n , m , cnt = 0;
Poly poly[N / 2];

class cmp{
public:
	bool operator()(int a, int b){
		return (int)poly[a].size() > (int)poly[b].size();
	}
};
priority_queue <int , vector<int> , cmp> Q;

int val[N];
int C(int x , int y){
	return 1ll * fac[x] * ifac[x - y] % p * ifac[y] % p;
}

int main(){
	ios::sync_with_stdio(0);
	cin >> n; m = (n << 1);
	for(int i = 1 ; i <= m ; ++ i){
		cin >> h[i];
		val[h[i]] ++;
	}
	init();
	for(int i = 1 ; i <= 100000 ; ++ i)
		if(val[i] > 1){
			++ cnt;
			poly[cnt].push_back(1);
			for(int j = 2 ; j <= val[i] ; j += 2)
				poly[cnt].push_back(1ll * C(val[i] , j) * r[j] % p);
			Q.push(cnt);
		}
	while(Q.size() > 1){
		int st1 = Q.top(); Q.pop(); int st2 = Q.top(); Q.pop();
		++ cnt;
		poly[cnt] = mul(poly[st1] , poly[st2]);
		Q.push(cnt);
	}
	int ans = r[m];
	if(Q.size() == 1){
		int sz = poly[cnt].size();
		for(int i = 1 ; i < sz ; ++ i){
			int now = 1ll * poly[cnt][i] * r[m - (i << 1)] % p;
			if(i % 2 == 0)
				ans = (ans + now) % p;
			else
				ans = (ans + p - now) % p;
		}
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 14352