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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
| const int L=18,N=1<<L|10,P=998244353;
ll qpow(ll x,ll k=P-2) { ll res=1; for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P; return res; }
int I[N],J[N]; int rev[N],w[N]; void Init(){ w[1<<(L-1)]=1; int t=qpow(3,(P-1)>>L); rep(i,(1<<(L-1))+1,1<<L) w[i]=1ll*w[i-1]*t%P; drep(i,(1<<(L-1))-1,1) w[i]=w[i<<1]; rep(i,J[0]=1,N-1) J[i]=1ll*J[i-1]*i%P; I[N-1]=qpow(J[N-1]); drep(i,N-1,1) I[i-1]=1ll*I[i]*i%P; } int Init(int n){ int R=1,c=-1; while(R<=n) R<<=1,c++; rep(i,0,R-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<c); return R; } void NTT(int n,V &A,int f) { static ull a[N]; if((int)A.size()<n) A.resize(n); rep(i,0,n-1) a[rev[i]]=A[i]; for(int i=1;i<n;i<<=1) { int *e=w+i; for(int l=0;l<n;l+=i*2) { for(int j=l;j<l+i;++j) { int t=a[j+i]*e[j-l]%P; a[j+i]=a[j]+P-t; a[j]+=t; } } } rep(i,0,n-1) A[i]=a[i]%P,Mod2(A[i]); if(f==-1) { reverse(A.begin()+1,A.end()); ll base=1ll*I[n]*J[n-1]%P; rep(i,0,n-1) A[i]=A[i]*base%P; } }
V operator + (V a,const V &b) { if(a.size()<b.size()) a.resize(b.size()); rep(i,0,b.size()-1) a[i]+=b[i],Mod1(a[i]); return a; } V operator - (V a,const V &b) { if(a.size()<b.size()) a.resize(b.size()); rep(i,0,b.size()-1) a[i]-=b[i],Mod2(a[i]); return a; } V operator * (V a,V b) { int n=a.size()-1,m=b.size()-1; int R=Init(n+m); NTT(R,a,1),NTT(R,b,1); rep(i,0,R-1) a[i]=1ll*a[i]*b[i]%P; NTT(R,a,-1),a.resize(n+m+1); return a; } V operator * (V a,const int &x) { for(int &i:a) i=1ll*i*x%P; return a; } V operator * (const int &x,V a) { return a*x; }
void println(const V &a){ for(int i:a) printf("%d ",i); puts(""); } V read(int n){ V A(n); rep(i,0,n-1) A[i]=rd(); return A; } V operator ~ (V a) { int n=a.size(),m=(n+1)>>1; if(n==1) return {(int)qpow(a[0])}; V b=a; b.resize(m),b=~b; int R=Init(n*2); NTT(R,a,1),NTT(R,b,1); rep(i,0,R-1) a[i]=(P+2-1ll*a[i]*b[i]%P)*b[i]%P; NTT(R,a,-1),a.resize(n); return a; } V Deriv(V a) { rep(i,0,a.size()-2) a[i]=1ll*(i+1)*a[i+1]%P; a.pop_back(); return a; } V Integ(V a){ a.pb(0); drep(i,a.size()-1,1) a[i]=1ll*a[i-1]*J[i-1]%P*I[i]%P; a[0]=0; return a; } V Ln(V a){ int n=a.size(); a=Deriv(a)*~a; return a.resize(n-1),Integ(a); } V Exp(V a) { if(a.size()==1) return assert(a[0]==0),V{1}; int n=a.size(); V b=a; b.resize((n+1)/2),b=Exp(b),b.resize(n); a=a-Ln(b),a[0]++; a=a*b,a.resize(n); return a; }
V operator << (V a,int x) { a.resize(a.size()+x); drep(i,a.size()-1,x) a[i]=a[i-x]; rep(i,0,x-1) a[i]=0; return a; } V operator >> (V a,int x) { if((int)a.size()<=x) return V{ }; rep(i,x,a.size()-1) a[i-x]=a[i]; a.resize(a.size()-x); return a; }
V Newton(int n){ if(n==1) return V{0}; if(n==2) return V{0,1}; V G=Newton((n+1)/2); G.resize(n); V IG=~(V{1}-G); V H=(2*G-G*G); H.resize(n),H=H*IG*((P+1)/2),H.resize(n),H=Exp(H)<<1; V F=IG*IG; F.resize(n),F[0]++; F=H*F,F.resize(n),F[0]-=2,Mod2(F[0]); F=G-2*(H-G)*~F; return F.resize(n),F; }
int main(){ int n=rd()+1; Init(); V F=Newton(n); rep(i,1,F.size()-1) F[i]=1ll*F[i]*I[i]%P*J[i-1]%P; F=Exp(F); printf("%d\n",int(1ll*F.back()*J[n-1]%P)); }
|