#include <iostream>
#include <vector>
#include <map>

#include <atcoder/convolution>
#include <atcoder/modint>

using namespace std;
using namespace atcoder;

using mint = modint998244353;

template<typename T>
struct Combination {
private:
  int sz;
  vector<T> F, F_;
public:
  Combination(int sz) : sz(sz), F(sz+1), F_(sz+1) {
    F[0] = 1;
    for(int i = 0; i < sz; ++i) F[i+1] = F[i]*(i+1);
    F_.back() = (T)1/F.back();
    for(int i = sz-1; i >= 0; --i) F_[i] = F_[i+1]*(i+1);
  }
  T C(int n, int k){
    assert(n <= sz);
    if(n < 0 or k > n) return (T)0;
    return F[n]*F_[k]*F_[n-k];
  }
};

int main(){
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  
  int N;
  cin >> N;
  map<int,int> H;
  for(int i = 0; i < 2*N; ++i){
    int h;
    cin >> h;
    ++H[h];
  }
  Combination<mint> comb(100001);
  vector<mint> C(1,1);
  for(auto [k, v] : H){
    if(v == 1) continue;
    vector<mint> T(v/2+1);
    T[0] = 1;
    for(int i = 0; i < v/2; ++i){
      T[i+1] = T[i]*comb.C(v-2*i,2)/(i+1);
    }
    C = convolution(C,T);
  }
  // cerr << C.size() << endl;
  // for(auto e : C)
  //   cerr << e.val() << " ";
  // cerr << endl;
  vector<mint> A(N+1);
  A[0] = 1;
  for(int i = 1; i <= N; ++i){
    A[i] = A[i-1]*comb.C(2*i,2)/i;
  }
  // for(auto e : A)
  //   cerr << e.val() << " ";
  // cerr << endl;
  mint ans = 0;
  for(int i = 0; i < C.size(); ++i){
    if(C[i] == 0) continue;
    ans += C[i]*(i%2 ? -1 : 1)*A[N-i];
  }
  cout << ans.val() << endl;
}
