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

#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i)
#define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i)

mt19937 Rnd(chrono::high_resolution_clock::now().time_since_epoch().count());

template <typename T>
inline void chkmax(T &x, T y) { if (x < y) x = y; }

template <typename T>
inline void chkmin(T &x, T y) { if (x > y) x = y; }

inline int read() {
  #define nc getchar()
  int x = 0;
  char c = nc;
  while (c < 48) c = nc;
  while (c > 47) x = x * 10 + (c ^ 48), c = nc;
  return x;
  #undef nc
}

typedef long long ll;
typedef vector <int> vi;
typedef pair <int, int> pii;

#define P 998244353

const int maxn = 3e5 + 10, MAXN = 3e5 + 10;

int Inc(int x, int y) {
  return x + y < P ? x + y : x + y - P;
}

int Dec(int x, int y) {
  return x < y ? x - y + P : x - y;
}

void Add(int &x, int y) {
  x += y;
  if (x >= P) x -= P;
}

void Sub(int &x, int y) {
  x -= y;
  if (x < 0) x += P;
}

int qp(int a, int k) {
  int res = 1;
  for (; k; k >>= 1, a = 1ll * a * a % P) {
    if (k & 1) res = 1ll * res * a % P;
  }
  return res;
}

int pw2[maxn], inv[maxn], fac[maxn], ifac[maxn];

int binom(int n, int m) {
  return n < m ? 0 : 1ll * fac[n] * ifac[m] % P * ifac[n - m] % P;
}

void init() {
  pw2[0] = 1, pw2[1] = 2;
  fac[0] = ifac[0] = 1;
  inv[1] = fac[1] = ifac[1] = 1;
  rep(i, 2, maxn - 1) {
    pw2[i] = Inc(pw2[i - 1], pw2[i - 1]);
    inv[i] = 1ll * (P - P / i) * inv[P % i] % P;
    fac[i] = 1ll * i * fac[i - 1] % P;
    ifac[i] = 1ll * inv[i] * ifac[i - 1] % P;
  }
}

int Pow( int x , int a ) {
	int ret = 1;
	while( a ) {
		if( a & 1 ) ret = ret * 1ll * x % P;
		x = x * 1ll * x % P , a >>= 1;
	}
	return ret;
}

int Wn[2][MAXN];
void getwn( int len ) {
	for( int mid = 1 ; mid < len ; mid <<= 1 ) {
		int w0 = Pow( 3 , ( P - 1 ) / ( mid << 1 ) ) , w1 = Pow( 3 , P - 1 - ( P - 1 ) / ( mid << 1 ) );
		Wn[0][mid] = Wn[1][mid] = 1;
		for( int i = 1 ; i < mid ; ++ i )
			Wn[0][mid + i] = Wn[0][mid + i - 1] * 1ll * w0 % P,
					Wn[1][mid + i] = Wn[1][mid + i - 1] * 1ll * w1 % P;
	}
}
int rev[MAXN];
void getr( int len ) {
	int l = __builtin_ctz( len ) - 1;
	for( int i = 1 ; i < len ; ++ i ) rev[i] = ( rev[i >> 1] >> 1 ) | ( ( i & 1 ) << l );
}
void NTT( vi& A , int len , int typ ) {
	for( int i = 0 ; i < len ; ++ i ) if( i < rev[i] ) swap( A[i] , A[rev[i]] );
	for( int mid = 1 ; mid < len ; mid <<= 1 )
		for( int i = 0 ; i < len ; i += ( mid << 1 ) )
			for( int j = i ; j < i + mid ; ++ j ) {
				int t0 = A[j] , t1 = A[j + mid] * 1ll * Wn[typ][j - i + mid] % P;
				A[j] = ( t0 + t1 > P ? t0 + t1 - P : t0 + t1 ) , A[j + mid] = ( t0 < t1 ? t0 - t1 + P : t0 - t1 );
			}
	if( typ ) for( int i = 0 , iv = Pow( len , P - 2 ) ; i < len ; ++ i ) A[i] = A[i] * 1ll * iv % P;
}
vi mul( vi a , vi b ) {
	int l = a.size() + b.size() - 1 , len = 1;
	if (l <= 100) {
	  vi as(l);
    rep(i, 0, a.size() - 1) rep(j, 0, b.size() - 1) {
      Add(as[i + j], 1ll * a[i] * b[j] % P);
    }
    return as;
  }
	while( len <= l ) len <<= 1;
	getr( len );
	a.resize( len ) , b.resize( len );
	vi as( len );
	NTT( a , len , 0 ) , NTT( b , len , 0 );
	rep( i , 0 , len - 1 ) as[i] = a[i] * 1ll * b[i] % P;
	NTT( as , len , 1 );
	as.resize( l );
	return as;
}

vi pol[MAXN];

vi divide(int l, int r) {
  if (l == r) return pol[l];
  int mid = r - 1, tmp = 0, cur = 0;
  rep(i, l, r) tmp += pol[i].size();
  rep(i, l, r - 1) if ((cur += pol[i].size()) * 2 >= tmp) {
    mid = i; break;
  }
  return mul(divide(l, mid), divide(mid + 1, r));
}

int n, tot, A[maxn], h[maxn];

void discretize() {
  static int data[maxn];
  memcpy(data, h, sizeof data);
  sort(data + 1, data + n + 1);
  tot = unique(data + 1, data + n + 1) - data - 1;
  rep(i, 1, n) A[h[i] = lower_bound(data + 1, data + tot + 1, h[i]) - data]++;
}

void solve() {
  init();
  cin >> n;
  n *= 2;
  rep(i, 1, n) h[i] = read();
  discretize();
  rep(i, 1, tot) {
//    printf("#%d\n", A[i]);
    pol[i].push_back(1);
    rep(j, 1, A[i] / 2) {
      int tmp = 1ll * binom(A[i], j + j) * fac[j + j] % P * qp(1ll * fac[j] * pw2[j] % P, P - 2) % P;
      pol[i].push_back(tmp);
    }
//    for (int x : pol[i]) printf("%d ", x);
//    puts("");
  }
//  puts("GG");
  vi data = divide(1, tot);
  int ans = 0;
  rep(i, 0, data.size() - 1) {
//    printf("!%d\n", data[i]);
    int t = n - i * 2, tmp = 1ll * fac[t] * qp(1ll * fac[t / 2] * pw2[t / 2] % P, P - 2) % P;
    ans = (ans + 1ll * (i & 1 ? -1 : 1) * data[i] * tmp % P + P) % P;
  }
  cout << ans << endl;
}

signed main() {
	getwn( 1 << 17 );
//  int T = read();
//  while (T--) solve();
  solve();
  return 0;
}


Measured memory_bytes: 21380