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
| #include <bits/stdc++.h> using namespace std; const int N = 2e5 + 5,P = 998244353,GG = 3; inline int Add(const int &a,const int &b) { return (a + b >= P) ? (a + b - P) : (a + b);} inline int Sub(const int &a,const int &b) { return (a < b) ? (a - b + P) : (a - b);} inline int qpow(int a,int b) { int res = 1;while(b) {if(b&1) res = 1ll * res * a % P;a = 1ll * a * a % P;b >>= 1;} return res;} const int Gi = qpow(GG,P - 2); int n; int Gs[N],Gs2[N],rev[N]; inline int GetLen(int x) { int len = 1; while(len <= x) len <<= 1; return len; } inline void calc_rev(int len) { for(int i = 0;i < len;i++) { rev[i] = rev[i >> 1] >> 1; if(i & 1) rev[i] |= len >> 1; } } int fac[N],ifac[N]; inline void init(int len) { for(int i = 1;i < len;i <<= 1) { Gs[i] = Gs2[i] = 1; Gs[i + 1] = qpow(GG,(P - 1) / (i << 1)); Gs2[i + 1] = qpow(Gi,(P - 1) / (i << 1)); for(int j = 2;j < i;j++) Gs[i + j] = 1ll * Gs[i + j - 1] * Gs[i + 1] % P, Gs2[i + j] = 1ll * Gs2[i + j - 1] * Gs2[i + 1] % P; } fac[0] = 1; for(int i = 1;i <= len;i++) fac[i] = 1ll * fac[i - 1] * i % P; ifac[1] = 1; for(int i = 2;i <= len;i++) ifac[i] = 1ll * ifac[P % i] * (P - P / i) % P; ifac[0] = 1; for(int i = 1;i <= len;i++) ifac[i] = 1ll * ifac[i - 1] * ifac[i] % P; } inline void NTT(int *F,int len,int type) { for(int i = 0;i < len;i++) if(i < rev[i]) swap(F[i],F[rev[i]]); for(int k = 1;k < len;k <<= 1) for(int j = 0;j < len;j += k + k) for(int i = 0;i < k;i++) { int cur = type == 1 ? Gs[k | i] : Gs2[k | i]; int u = F[i | j],v = 1ll * cur * F[i | j | k] % P; F[i | j] = Add(u,v); F[i | j | k] = Sub(u,v); } if(type == -1) for(int i = 0,Inv = qpow(len,P - 2);i < len;i++) F[i] = 1ll * F[i] * Inv % P; } int A[N],B[N];
int f[N],F[N],G[N]; void cdq(int l,int r) { if(l == r) { if(l > 1) { f[l] = 2ll * f[l] * fac[l - 1] % P; f[l] = Sub(f[l],1ll * (l - 1) * f[l - 1] % P); F[l] = 1ll * f[l] * ifac[l - 1] % P; G[l] = 1ll * f[l] * ifac[l] % P; } return; } int mid = l + r >> 1; cdq(l,mid); if(l == 1) { int len = GetLen((mid - l + 1) + (mid - l + 1)); for(int i = 0;i < len;i++) A[i] = B[i] = 0; for(int i = 0;i <= mid - l;i++) A[i] = F[i + 1],B[i] = G[i + 1]; calc_rev(len); NTT(A,len,1);NTT(B,len,1); for(int i = 0;i < len;i++) A[i] = 1ll * A[i] * B[i] % P; NTT(A,len,-1); for(int i = mid + 1;i <= r;i++) f[i] = Add(f[i],A[i - 2]); } else { int len = GetLen((r - l + 1) + (mid - l + 1)); for(int i = 0;i < len;i++) A[i] = B[i] = 0; for(int i = 0;i < r - l;i++) A[i] = F[i + 1]; for(int i = 0;i <= mid - l;i++) B[i] = G[i + l]; calc_rev(len); NTT(A,len,1);NTT(B,len,1); for(int i = 0;i < len;i++) A[i] = 1ll * A[i] * B[i] % P; NTT(A,len,-1); for(int i = mid + 1;i <= r;i++) f[i] = Add(f[i],A[i - l - 1]); for(int i = 0;i < len;i++) A[i] = B[i] = 0; for(int i = 0;i < r - l;i++) A[i] = G[i + 1]; for(int i = 0;i <= mid - l;i++) B[i] = F[i + l]; calc_rev(len); NTT(A,len,1);NTT(B,len,1); for(int i = 0;i < len;i++) A[i] = 1ll * A[i] * B[i] % P; NTT(A,len,-1); for(int i = mid + 1;i <= r;i++) f[i] = Add(f[i],A[i - l - 1]); } cdq(mid + 1,r); } int main() { cin >> n; f[1] = F[1] = G[1] = 1; int len = GetLen(n * 2); init(len); cdq(1,n); cout << ((f[n] - 1) * 2ll) % P << endl; return 0; }
|