#include <iostream>
#include <vector>
#include <queue>
#include <functional>

using namespace std;


const int MOD = 998244353;

long long modPow(long long a, long long p){
    if(p == 0) return 1;
    auto res = modPow(a, p/2);
    res = (res*res)%MOD;
    if(p%2) res = (res*a)%MOD;
    return res;
}

long long calcInv(long long a){
    return modPow(a, MOD-2);
}

void ntt(vector<long long>& v, int inv){
    const int n = v.size();
    auto w = modPow(3, (MOD-1)/n);
    if(inv == -1) w = calcInv(w);
    int rev = 0;
    for(int i=1;i<n-1;i++){
        for(int j=n/2;j>(rev^=j);j/=2);
        if(i < rev) swap(v[i], v[rev]);
    }
    for(int m=1;m<n;m*=2){
        auto cur = 1;
        auto rot = modPow(w, n/(2*m));
        for(int i=0;i<m;i++){
            for(int j=i;j<n;j+=2*m){
                auto p = v[j];
                auto q = v[j+m] * cur % MOD;
                v[j] = (p + q) % MOD;
                v[j+m] = (p + MOD - q) % MOD;
            }
            cur = (cur * rot) % MOD;
        }
    }
}

vector<long long> convolution(const vector<long long>& a, const vector<long long>& b){
    int _n = a.size() + b.size();
    int n = 1;
    while(n < _n) n *= 2;
    vector<long long> na(n, 0), nb(n, 0);
    for(int i=0;i<a.size();i++) na[i] = a[i];
    for(int i=0;i<b.size();i++) nb[i] = b[i];
    ntt(na, 1);
    ntt(nb, 1);
    for(int i=0;i<n;i++) na[i] = na[i] * nb[i] % MOD;
    ntt(na, -1);
    auto inv = calcInv(n);
    for(int i=0;i<n;i++) na[i] = na[i] * inv % MOD;
    na.resize(a.size() + b.size() - 1);
    return na;
}

bool op(const vector<long long>& a, const vector<long long>& b){ return a.size() < b.size(); }

int main(){
    const int maxSize = 100001;
    vector<long long> inv(maxSize);
    vector<long long> fact(maxSize);
    vector<long long> factInv(maxSize);
    for(int i=0;i<2;i++) inv[i] = fact[i] = factInv[i] = 1;
    for(int i=2;i<maxSize;i++){
        inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
        fact[i] = fact[i-1] * i % MOD;
        factInv[i] = factInv[i-1] * inv[i] % MOD;
    }
    auto comb = [&](int n, int r){
        if(n < r || r < 0) return 0LL;
        return fact[n] * factInv[n-r] % MOD * factInv[r] % MOD;
    };
    auto perm = [&](int n, int r){
        if(n < r || r < 0) return 0LL;
        return fact[n] * factInv[n-r] % MOD;
    };
    vector<long long> inv2pow(maxSize);
    inv2pow[0] = 1;
    for(int i=1;i<maxSize;i++) inv2pow[i] = inv2pow[i-1] * inv[2] % MOD;
    int N; cin >> N;
    vector<int> cnt(100001, 0);
    for(int i=0;i<2*N;i++){
        int h; cin >> h;
        cnt[h]++;
    }
    vector<vector<long long>> p(100001);
    priority_queue<int, vector<int>, function<bool(int, int)>> qu(
        [&](int a, int b){ return p[a].size() > p[b].size(); }
    );
    p[0].push_back(1);
    qu.push(0);
    for(int i=0;i<cnt.size();i++){
        int t = cnt[i];
        if(t < 2) continue;
        vector<long long> v(t/2 + 1);
        v[0] = 1;
        for(int i=1;i<v.size();i++){
            v[i] = perm(t, 2*i) * inv2pow[i] % MOD * factInv[i] % MOD;
        }
        p[i] = v;
        qu.emplace(i);
    }
    while(qu.size() >= 2){
        auto a = qu.top(); qu.pop();
        auto b = qu.top(); qu.pop();
        p[a] = convolution(p[a], p[b]);
        qu.emplace(a);
    }
    long long res = 0;
    auto& v = p[qu.top()];
    for(int i=0;i<v.size();i++){
        long long rest = N-i;
        long long cur = perm(2*rest, rest) * inv2pow[rest] % MOD;
        if(i%2){
            res = (res + MOD - cur * v[i] % MOD) % MOD;
        } else {
            res = (res + cur * v[i]) % MOD;
        }
    }
    cout << res << endl;
}

Measured memory_bytes: 17240