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) (judge verdict: Wrong Answer)

//Author - Rahil Malhotra
#include <bits/stdc++.h>
using namespace std;
 
template <typename T> void print(T t) { cout<<t<<endl; }
template<typename T, typename... Args> void print(T t, Args... args) { cout<<t<<" "; print(args...); }
 
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl '\n'
#define int long long
#define double long double

int mod=998244353;
int md=998244353;

inline void add(int &a, int b) {
  a += b;
  if (a >= md) a -= md;
}

inline void sub(int &a, int b) {
  a -= b;
  if (a < 0) a += md;
}

inline int mul(int a) {
  return a;
}

template<typename... T>
inline int mul(int a, T... b) {
  return (int) ((long long) a * mul(b...) % md);
}

inline int power(int a, long long b) {
  int res = 1;
  while (b > 0) {
    if (b & 1) {
      res = mul(res, a);
    }
    a = mul(a, a);
    b >>= 1;
  }
  return res;
}

inline int inv(int a) {
  a %= md;
  if (a < 0) a += md;
  int b = md, u = 0, v = 1;
  while (a) {
    int t = b / a;
    b -= t * a; swap(a, b);
    u -= t * v; swap(u, v);
  }
  assert(b == 1);
  if (u < 0) u += md;
  return u;
}

namespace ntt {
  int base = 1;
  vector<int> roots = {0, 1};
  vector<int> rev = {0, 1};
  int max_base = -1;
  int root = -1;

  void init() {
    int tmp = md - 1;
    max_base = 0;
    while (tmp % 2 == 0) {
      tmp /= 2;
      max_base++;
    }
    root = 2;
    while (true) {
      if (power(root, 1 << max_base) == 1) {
        if (power(root, 1 << (max_base - 1)) != 1) {
          break;
        }
      }
      root++;
    }
  }

  void ensure_base(int nbase) {
    if (max_base == -1) {
      init();
    }
    if (nbase <= base) {
      return;
    }
    assert(nbase <= max_base);
    rev.resize(1 << nbase);
    for (int i = 0; i < (1 << nbase); i++) {
      rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
    }
    roots.resize(1 << nbase);
    while (base < nbase) {
      int z = power(root, 1 << (max_base - 1 - base));
      for (int i = 1 << (base - 1); i < (1 << base); i++) {
        roots[i << 1] = roots[i];
        roots[(i << 1) + 1] = mul(roots[i], z);
      }
      base++;
    }
  }

  void fft(vector<int> &a) {
    int n = (int) a.size();
    assert((n & (n - 1)) == 0);
    int zeros = __builtin_ctz(n);
    ensure_base(zeros);
    int shift = base - zeros;
    for (int i = 0; i < n; i++) {
      if (i < (rev[i] >> shift)) {
        swap(a[i], a[rev[i] >> shift]);
      }
    }
    for (int k = 1; k < n; k <<= 1) {
      for (int i = 0; i < n; i += 2 * k) {
        for (int j = 0; j < k; j++) {
          int x = a[i + j];
          int y = mul(a[i + j + k], roots[j + k]);
          a[i + j] = x + y - md;
          if (a[i + j] < 0) a[i + j] += md;
          a[i + j + k] = x - y + md;
          if (a[i + j + k] >= md) a[i + j + k] -= md;
        }
      }
    }
  }

  vector<int> multiply(vector<int> a, vector<int> b, int eq = 0) {
    int need = (int) a.size() + (int) b.size() - 1;
    int nbase = 0;
    while ((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz);
    b.resize(sz);
    fft(a);
    if (eq) b = a; else fft(b);
    int inv_sz = inv(sz);
    for (int i = 0; i < sz; i++) {
      a[i] = mul(mul(a[i], b[i]), inv_sz);
    }
    reverse(a.begin() + 1, a.end());
    fft(a);
    a.resize(need);
    return a;
  }

  vector<int> square(vector<int> a) {
    return multiply(a, a, 1);
  }
}

int n;
map<int,int>mp;
int fact[200005];
int premul[200005];
int inver(int x)
{
    int r,y;
    for(r=1,y=mod-2;y>0;x=(x*x)%mod,y/=2)
        if(y%2==1)
            r=r*x%mod;
    return r;
}
int nCr(int n, int m)
{
    if(n<m)
        return 0;
    return fact[n] *inver(fact[m])%mod *inver(fact[n-m])%mod ;
}
int32_t main()
{
    IOS;
    cin>>n;
    premul[1]=1;
    for(int i=3;i<=2*n-1;i++)
        premul[i]=(i*premul[i-2])%mod;
    fact[0]=1;
    for(int i=1;i<=200001;i++)
        fact[i]=(i*fact[i-1])%mod;
    for(int i=0;i<2*n;i++)
    {
        int a;
        cin>>a;
        mp[a]++;
    }
    int grp=mp.size();
    vector<int>v[grp];
    int ctr=0;
    for(auto i:mp)
    {
        v[ctr].push_back(1);
        int sz=i.second;
        int val=1;
        for(int j=2;j<=sz;j+=2)
        {
            val=(val*nCr(sz-j+2,2))%mod;
            v[ctr].push_back(val);
        }
        ctr++;
    }
    // for(int i=0;i<grp;i++)
    // {
    //     for(int j:v[i])
    //         cout<<j<<" ";
    //     cout<<endl;
    // }
    vector<int>fin;
    fin.push_back(1);
    for(int i=0;i<grp;i++)
        fin=ntt::multiply(fin,v[i]);

    int ct=n;
    int ans=0;
    int st=0;
    for(auto i:fin)
    {
        if(st%2==0)
        {
            int get=0;
            if(ct==0)
                get=i;
            else
                get=(premul[2*ct-1]*i)%mod;
            ans=(ans+get)%mod;
        }
        else
        {
            int get=0;
            if(ct==0)
                get=i;
            else
                get=(premul[2*ct-1]*i)%mod;
            ans=(ans-get+mod)%mod;
        }
        //cout<<st<<" "<<ct<<" "<<i<<" "<<ans<<endl;
        ct--;
        st++;
        //cout<<i<<" ";
    }
    cout<<ans<<endl;
}