
//region Template
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#ifdef LOCAL
#include <debug_prettyprint.hpp>
#else
#define debug(...) 42
#pragma GCC optimize("Ofast")
#pragma GCC target("avx")
#endif
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cout<<fixed<<setprecision(12);
#define FOR(i, n) for(int i=0; i<int(n); i++)
#define RNG(i, f, t) for(int i=int(f); i<=int(t); i++)
#define REV(i, f, t) for(int i=int(f); i>=int(t); --i)
#define ALL(v) (v).begin(), (v).end()
#define EXIT(answer) { cerr<<"EXIT #"<<__LINE__<<endl; cout<<answer<<endl; exit(0); }
#define sz(v) int(v.size())
template<int,typename T> struct MINMAX{ T val; MINMAX(T val) : val(val) {} };
template<typename T> MINMAX<1,T> MAX(T val) { return MINMAX<1,T>(val); };
template<typename T> MINMAX<2,T> MIN(T val) { return MINMAX<2,T>(val); };
template<typename T, typename U> inline T& operator|=(T &lhs, MINMAX<1,U> rhs) { return lhs = max(lhs, rhs.val); }
template<typename T, typename U> inline T& operator|=(T &lhs, MINMAX<2,U> rhs) { return lhs = min(lhs, rhs.val); }
template<typename T, typename U> istream& operator>>(istream& in, pair<T,U> &p) { in>>p.first>>p.second; return in; }
template<typename T=int> inline vector<T> READ(int n) { vector<T> vec(n); FOR(i,n) cin>>vec[i]; return vec; }
template<typename T> using min_heap = priority_queue<T, vector<T>, greater<T> >;
typedef signed long long int ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
//endregion


const int MOD = 998244353;
const int MAXN = 1e5+5;

ll fac[MAXN+1];
ll invfac[MAXN+1];

ll inverseModulo(ll a, ll b){
    return 1<a ? b - inverseModulo(b % a, a) * b / a : 1;
}
ll binomial(int n, int k) {
    assert(k>=0 && k<=n);
    if(k==0 || n-k==0) return 1;
    return fac[n] * invfac[k] % MOD * invfac[n-k] % MOD;
}

ll memo[MAXN]={0};
ll pairs(int x) {
    if(x==1) return 1;
    if(x%2==0) return pairs(x-1);
    if(memo[x] > 0) return memo[x];
    return memo[x] = x * pairs(x-2) % MOD;
}

signed main() {
    FASTIO

    fac[0]=1;
    invfac[0]=1;
    RNG(i,1,MAXN) {
        fac[i] = 1LL*i*fac[i-1] % MOD;
        invfac[i] = inverseModulo(fac[i], MOD);
    }

    int n; cin>>n; n *= 2;
    vi h = READ(n);

    map<int,int> cnt;

    for(auto x : h)
        cnt[x]++;

    min_heap<vi> pq;

    for(auto e : cnt) {
        int rem = e.second;
        vi poly = {1};
        while(rem>=2) {
            int ways = binomial(rem, 2);
            poly.push_back(ways);
            rem -= 2;
        }
        pq.push(poly);
    }

    while(pq.size()>=2) {
        vi a = pq.top(); pq.pop();
        vi b = pq.top(); pq.pop();
        vi c = convolution<MOD>(a,b);
        pq.push(c);
    }

    vi poly = pq.top();

    ll ans=0;

    FOR(i,poly.size()) {
        int sgn = i%2 ? -1 : 1;
        ans += sgn * poly[i] * pairs(n-i*2);
        ans %= MOD;
    }

    cout<<ans<<endl;

}