1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| #include <bits/stdc++.h> using namespace std; const int N = 4e5 + 5; int n, h[N], cnt[N], d[N], sd[N]; int *f[N], buf[N<<5], *np(buf); int fac[N], ifac[N], g[N]; const int mod = 998244353, G = 3; int up, w[N], rev[N], inv[N]; int fpw(int a, int b) { int ans = 1; while(b) { if(b&1) ans = 1ll*ans*a%mod; a = 1ll*a*a%mod; b >>= 1; } return ans; } void myassert(bool x) { if(!x) while(true); } namespace poly { void init(int n) { inv[0] = inv[1] = 1; for(int i=2; i<=n; i++) inv[i] = 1ll*(mod-mod/i)*inv[mod%i]%mod; up = 1; int l = 0; while(up<=n) up <<= 1, l++; for(int i=0; i<up; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(l-1)); int wn = fpw(G, mod>>l); w[up>>1] = 1; for(int i=(up>>1)+1; i<up; i++) w[i] = 1ll*w[i-1]*wn%mod; for(int i=(up>>1)-1; i>=1; i--) w[i] = w[i<<1]; } void clear(int *a, int n) { memset(a, 0, n<<2); } int getlen(int n) { return 1<<(32-__builtin_clz(n)); } inline void mul(int *a, int n, int x, int *b) { while(n--) *b++ = 1ll**a++*x%mod; } inline void dot(int *a, int *b, int n, int *c) { while(n--) *c++ = 1ll**a++**b++%mod; } void DFT(int *a, int l) { static unsigned long long tmp[N]; int u = __builtin_ctz(up/l), t; for(int i=0; i<l; i++) tmp[i] = a[rev[i]>>u]; for(int i=1; i^l; i<<=1) for(int j=0, d=i<<1; j^l; j+=d) for(int k=0; k<i; k++) t = tmp[i|j|k]*w[i|k]%mod, tmp[i|j|k] = tmp[j|k]+mod-t, tmp[j|k] += t; for(int i=0; i<l; i++) a[i] = tmp[i]%mod; } void IDFT(int *a, int l) { reverse(a+1, a+l); DFT(a, l); mul(a, l, mod-mod/l, a); } inline void conv(int *a, int *b, int l) { DFT(a, l); DFT(b, l); dot(a, b, l, a); IDFT(a, l); } void mul(int *a, int n, int *b, int m, int *c) { static int l, ta[N], tb[N]; if(n+m==0) { c[0] = 1ll*a[0]*b[0]%mod; return; } l = getlen(n+m); for(int i=0; i<=n; i++) ta[i] = a[i]; for(int i=0; i<=m; i++) tb[i] = b[i]; conv(ta, tb, l); for(int i=0; i<=n+m; i++) c[i] = ta[i]; clear(ta, l), clear(tb, l); } } void init(int n) { fac[0] = 1; for(int i=1; i<=n; i++) fac[i] = 1ll*fac[i-1]*i%mod; ifac[n] = fpw(fac[n], mod-2); for(int i=n-1; i>=0; i--) ifac[i] = 1ll*ifac[i+1]*(i+1)%mod; } int comb(int a, int b) { if(a<b||b<0||a<0) return 0; return 1ll*fac[a]*ifac[b]%mod*ifac[a-b]%mod; } void solve(int p, int l, int r) { f[p] = np, np += sd[r] - sd[l-1] + 1; if(l==r) { int cur = 1; for(int i=0; i<=d[l]; i++) { f[p][i] = cur; cur = 1ll*cur*comb(cnt[l]-2*i, 2)%mod*inv[i+1]%mod; } return; } int mid = (l+r)>>1; solve(p<<1, l, mid); solve(p<<1|1, mid+1, r); poly::mul(f[p<<1], sd[mid]-sd[l-1], f[p<<1|1], sd[r]-sd[mid], f[p]); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; int mx = 0; init(2*n); poly::init(n); for(int i=1; i<=2*n; i++) { cin >> h[i]; cnt[h[i]]++; mx = max(mx, h[i]); } for(int i=1; i<=mx; i++) { d[i] = cnt[i]/2; sd[i] = sd[i-1] + d[i]; } solve(1, 1, mx); for(int i=0; i<=sd[mx]; i++) g[i] = 1ll*f[1][i]*fac[2*n-2*i]%mod*ifac[n-i]%mod*fpw(fpw(2, n-i), mod-2)%mod; int ans = 0; for(int i=0; i<=sd[mx]; i++) { if(i&1) ans = (ans - g[i] + mod)%mod; else ans = (ans + g[i])%mod; } cout << ans << '\n'; return 0; }
|