Problem:
Score : 600 points

Problem Statement

There are 2N people numbered 1 through 2N.
The height of Person i is h_i.

How many ways are there to make N pairs of people such that the following conditions are satisfied?
Compute the answer modulo 998,244,353.

Each person is contained in exactly one pair.

For each pair, the heights of the two people in the pair are different.

Two ways are considered different if for some p and q, Person p and Person q are paired in one way and not in the other.

Constraints

1 \leq N \leq 50,000

1 \leq h_i \leq 100,000

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
h_1
:
h_{2N}

Output

Print the answer.

Sample Input 1

2
1
1
2
3

Sample Output 1

2

There are two ways:

Form the pair (Person 1, Person 3) and the pair (Person 2, Person 4).

Form the pair (Person 1, Person 4) and the pair (Person 2, Person 3).

Sample Input 2

5
30
10
20
40
20
10
10
30
50
60

Sample Output 2

516

Solution in C++ (GCC 9.2.1 with AC Library v1.1) (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <unistd.h>
#include <stdlib.h>
#include <atcoder/convolution>

using namespace std;
using namespace atcoder;

// using mint = long double;
// using mint = modint998244353;
// using mint = modint1000000007;

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<P, ll> T;
typedef pair<ll, vector<ll>> Pd;

const ll INF = 2e18;
const ll fact_table = 3200008;

priority_queue <ll> pql;
priority_queue <P> pqp;
//big priority queue
priority_queue <ll, vector<ll>, greater<ll> > pqls;
priority_queue <P, vector<P>, greater<P> > pqps;
//small priority queue
//top pop

ll dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
ll dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};
//↓,→,↑,←

/*
#define endl "\n"
#ifdef ENJAPMA
#undef endl
#endif
*/

#define p(x) cout<<x<<endl;
#define el cout<<endl;
#define pe(x) cout<<x<<" ";
#define ps(x) cout<<fixed<<setprecision(25)<<x<<endl;
#define pu(x) cout<<(x);
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define CLEAR(a) a = decltype(a)();
#define pc(x) cout << x << ",";
#define rep(i, n) for (ll i = 0; i < (n); i ++)

typedef vector<ll> vec;
typedef vector<vector<ll>> mat;

const ll mod = 998244353ll;
// const ll mod = 1000000007ll;

ll mypow(ll a, ll b, ll m = mod) {ll x = 1; while (b) {while (!(b & 1)) {(a *= a) %= m; b >>= 1;}(x *= a) %= m; b--;} return x;}
vec readvec(ll read) { vec res(read); for (int i = 0; i < read; i++) { cin >> res[i]; } return res;}
void YES(bool cond) { if (cond) { p("YES");} else { p("NO");} return;}
void Yes(bool cond) { if (cond) { p("Yes");} else { p("No");} return;}
void line() { p("--------------------"); return;}


ll fact[fact_table + 5], rfact[fact_table + 5];

void c3_init() {
    fact[0] = rfact[0] = 1;
    for (ll i = 1; i <= fact_table; i++) {
        fact[i] = (fact[i - 1] * i) % mod;
    }
    rfact[fact_table] = mypow(fact[fact_table], mod - 2, mod);
    for (ll i = fact_table; i >= 1; i--) {
        rfact[i - 1] = rfact[i] * i;
        rfact[i - 1] %= mod;
    }
    return;
}
ll c3(ll n, ll r) {
    return (((fact[n] * rfact[r]) % mod ) * rfact[n - r]) % mod;
}


bool multicase = false;

ll cnt[100005], dp[100005];

ll c2table[100005], rc2table[100005];

ll makepair(ll size, ll num) {
    ll res1 = c2table[size];
    ll res2 = rc2table[size - num * 2];
    ll res = (res1 * res2) % mod;
    res *= rfact[num];
    res %= mod;
    return res;
}

void pre_calc() {
    c2table[1] = c2table[0] = 1;
    c2table[2] = 1, c2table[3] = 3;
    for (int i = 4; i <= 100000; i++) {
        c2table[i] = c2table[i - 2] * c3(i, 2);
        c2table[i] %= mod;
    }
    rc2table[100000] = mypow(c2table[100000], mod - 2, mod);
    rc2table[99999] = mypow(c2table[99999], mod - 2, mod);
    for (int i = 99998; i >= 0; i--) {
        rc2table[i] = rc2table[i + 2] * c3(i + 2, 2);
        rc2table[i] %= mod;
        assert(c2table[i] == mypow(rc2table[i], mod - 2, mod));
    }
    return;
}


void solve() {
    ll n;
    cin >> n;
    c3_init();
    pre_calc();
    for (int i = 0; i < 2 * n; i++) {
        ll val;
        cin >> val;
        cnt[val] ++;
    }
    dp[0] = 1;
    multiset<Pd> st;
    for (int i = 1; i <= 100000; i++) {
        ll size = cnt[i];
        if (size <= 1) continue;

        vec v = {1};

        for (int k = 1; k * 2ll <= size; k++) {
            ll p = makepair(size, k);
            v.pb(p);
        }

        ll len = v.size();

        st.insert({len, v});
    }

    st.insert({1ll, {1ll}});

    while (st.size() > 1) {
        Pd res1 = *st.begin();
        st.erase(st.begin());
        Pd res2 = *st.begin();
        st.erase(st.begin());

        vec r1 = res1.second, r2 = res2.second;

        vec c = atcoder::convolution(r1, r2);
        st.insert({res1.first + res2.first - 1, c});
    }

    vec finaldp = (*st.begin()).second;

    for (int i = 0; i <= n; i++) {
        if (i + 1 > finaldp.size()) {
            dp[i] = 0;
        } else {
            dp[i] = finaldp[i];
        }
    }

    ll value = 1ll, s = 2ll * n;
    ll chose = n;
    for (int i = 0; i <= n; i++) {
        dp[i] *= ((value * c2table[s]) % mod);
        dp[i] %= mod;

        value *= chose; 
        chose --;

        value %= mod;

        s -= 2;
    }
    ll sign = 1ll, ans = 0;
    for (int i = 0; i <= n; i++) {
        ans += (sign * dp[i] + mod);
        ans %= mod;
        sign *= -1;
    }
    ans *= mypow(fact[n], mod - 2, mod);
    ans %= mod;
    p(ans);
    return;
}


int main() {
    // init();
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    ll q, testcase = 1;
    if (multicase) {
        cin >> q;
    } else {
        q = 1;
    }
    while (q--) {
        // pu("Case ");pu("#");pu(testcase);pu(": ");
        solve();
        testcase++;
    }

    // solve();
    return 0;
}