//#define FFT_
//#define FAST
//#define SECURE
#ifdef FFT_
#ifdef FAST
#define FAST_FAST_TLE_
#endif
#ifdef SECURE
#define HIGH_PRECISION
#endif
#endif
#ifdef FAST
#include<bits/extc++.h>
#endif
namespace Math{
const int P=998244353,G=3,Gi=332748118;
typedef vector<int> Vec;
typedef unsigned long long ull;
inline ll fpow(ll a,int b,int MOD=P,ll c=1)
{
for(;b;b>>=1,a=a*a%MOD)if(b&1)c=c*a%MOD;
return c;
}
inline int inv(int x,int MOD=P){return fpow(x,MOD-2);}
inline int extend(int x)
{
int n=1;
while(n<x)n<<=1;
return n;
}
inline int add(int x){return x>P?x-P:x;}
inline int sub(int x){return x<0?x+P:x;}
inline void add(int &x,int y){(x+=y)>=P&&(x-=P);}
inline void sub(int &x,int y){(x-=y)<0&&(x+=P);}
inline int BSGS(int a,int b,int p)
{
#ifdef FAST
__gnu_pbds::gp_hash_table<int,int>mp;
#else
unordered_map<int,int>mp;
#endif
int m=ceil(sqrt(p));//ceil!!
for(int i=0;i<=m;b=1ll*a*b%p,++i)mp[b]=i;
a=fpow(a,m);
for(int i=0,j=1;i<m;j=1ll*j*a%p)
if(mp.find(j)!=mp.end()&&i*m>=mp[j])
return i*m-mp[j];
return -1;
}
inline int root(int p)
{
Vec fac;
int phi=p-1,x=phi;
for(int i=2;i*i<=x;++i)
if(x%i==0){
fac.push_back(i);
while(x%i==0)x/=i;
}
if(x>1)fac.push_back(x);
for(int i=2;i<=phi;++i)
{
bool flag=1;
for(auto j:fac)if(fpow(i,phi/j,p)==1){flag=0;break;}
if(flag)return i;
}
return -1;
}
int degree(int a,int k,int p)
{
int g=root(p);
int x=BSGS(g,a,p);
assert(x>=0&&x%k==0);
int r=fpow(g,x/k,p);
return min(r,p-r);
}
}
using namespace Math;
namespace Poly{
#define lg2(x) (31-__builtin_clz(x))
namespace FFT{
#ifdef HIGH_PRECISION
typedef __float128 db;
#else
typedef double db;
#endif
const db PI=acos(-1);
struct complex{
db x,y;
complex(){}
explicit complex(db _x,db _y):x(_x),y(_y){}
};
typedef vector<complex> Vex;
inline complex operator + (const complex &a,const complex &b){return complex(a.x+b.x,a.y+b.y);}
inline complex operator - (const complex &a,const complex &b){return complex(a.x-b.x,a.y-b.y);}
inline complex operator * (const complex &a,const complex &b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
inline complex& operator += (complex &a,const complex &b){return a=a+b;}
inline complex& operator -= (complex &a,const complex &b){return a=a-b;}
inline complex& operator *= (complex &a,const complex &b){return a=a*b;}
inline void FFT(Vex &a,int opt)
{
int n=a.size(),L=lg2(n);
Vec R(n);
for(int i=0;i<n;++i)
{
R[i]=R[i>>1]>>1|(i&1)<<(L-1);
if(i<R[i])swap(a[i],a[R[i]]);
}
for(int len=1;len<n;len<<=1)
{
complex O=complex(cos(PI/len),opt*sin(PI/len));
for(int i=0;i<n;i+=len<<1)
{
complex o=complex(1,0);
for(int j=0;j<len;++j,o=o*O)
{
complex Nx=a[i+j],Ny=o*a[i+j+len];
a[i+j]=Nx+Ny,a[i+j+len]=Nx-Ny;
}
}
}
}
inline void DFT(Vex &a){FFT(a,1);}
inline void IDFT(Vex &a){
FFT(a,-1);
int n=a.size();
for(auto &i:a)
#ifdef FAST_FAST_TLE_
i.y/=2*n;
#else
i.x/=n;
#endif
}
Vec mul(Vec a,Vec b)
{
int n=a.size()+b.size()-1,N=extend(n);
a.resize(N),b.resize(N);
#ifdef FAST_FAST_TLE_
Vex A(N);
for(int i=0;i<N;++i)A[i]=complex(a[i],b[i]);
DFT(A);
for(auto &i:A)i*=i;
IDFT(A);
for(int i=0;i<N;++i)a[i]=(int)(A[i].y+0.5);
#else
Vex A(N),B(N);
for(int i=0;i<N;++i)A[i].x=a[i],B[i].x=b[i];
DFT(A),DFT(B);
for(int i=0;i<N;++i)A[i]*=B[i];
IDFT(A);
for(int i=0;i<N;++i)a[i]=(int)(A[i].x+0.5);
#endif
return a.resize(n),a;
}
}
namespace NTT{
inline void NTT(Vec &a,int opt)
{
int n=a.size(),L=lg2(n);
Vec R(n);
vector<ull>t(n);
copy(a.begin(),a.end(),t.begin());
for(int i=0;i<n;++i)
{
R[i]=R[i>>1]>>1|(i&1)<<(L-1);
if(i<R[i])swap(t[i],t[R[i]]);
}
for(int len=1;len<n;len<<=1)
{
ll O=fpow(opt==1?G:Gi,(P-1)/(len<<1));
for(int i=0;i<n;i+=(len<<1))
{
ll o=1;
for(int j=0;j<len;++j,o=o*O%P)
{
int tmp=o*t[i+j+len]%P;
t[i+j+len]=t[i+j]-tmp+P;
t[i+j]+=tmp;
}
}
}
for(int i=0;i<n;++i)a[i]=t[i]%P;
}
inline void DFT(Vec &a){NTT(a,1);}
inline void IDFT(Vec &a)
{
NTT(a,-1);
int Inv=inv(a.size());
for(auto &i:a)i=1ll*i*Inv%P;
}
Vec mul(Vec a,Vec b)
{
int n=a.size()+b.size()-1,N=extend(n);
a.resize(N),b.resize(N);
DFT(a),DFT(b);
for(int i=0;i<N;++i)a[i]=1ll*a[i]*b[i]%P;
IDFT(a);
return a.resize(n),a;
}
}
#ifdef FFT_
using FFT::mul;
using FFT::DFT;
using FFT::IDFT;
#else
using NTT::mul;
using NTT::DFT;
using NTT::IDFT;
#endif
Vec operator * (const Vec &a,const Vec &b){return mul(a,b);}
Vec& operator *= (Vec &a,const Vec &b){return a=a*b;}
#ifndef FFT_
Vec operator ~ (Vec);
Vec fix(Vec,int);
Vec operator - (Vec A,Vec B)
{
int n=max(A.size(),B.size());
A.resize(n),B.resize(n);
for(int i=0;i<n;++i)A[i]=sub(A[i]-B[i]);
return A;
}
Vec operator - (Vec A){
for(auto i:A)i=sub(-i);
return A;
}
Vec operator - (int v,Vec A){
sub(A[0],v);
return A;
}
Vec operator - (Vec A,int v){
sub(A[0],v);
return A;
}
Vec operator + (int v,Vec A){
add(A[0],v);
return A;
}
Vec operator + (Vec A,int v){
add(A[0],v);
return A;
}
Vec operator + (Vec A,Vec B){
int n=max(A.size(),B.size());
A.resize(n),B.resize(n);
for(int i=0;i<n;++i)A[i]=add(A[i]+B[i]);
return A;
}
Vec operator / (Vec A,Vec B)
{
int n=A.size()-B.size()+1;
if(n<=0)return Vec(1,0);
reverse(A.begin(),A.end());
reverse(B.begin(),B.end());
A.resize(n),B.resize(n);
A=fix(A*~B,n);
return reverse(A.begin(),A.end()),A;
}
Vec operator % (Vec A,Vec B){int n=B.size()-1;return fix(A-A/B*B,n);}
Vec operator ~ (Vec A)
{
int n=A.size(),N=extend(n);
A.resize(N);
Vec I(N);
I[0]=inv(A[0]);
for(int l=2;l<=N;l<<=1)
{
Vec X(l),Y(l);
copy(A.begin(),A.begin()+l,X.begin());
copy(I.begin(),I.begin()+l,Y.begin());
int L=l<<1;
X.resize(L),Y.resize(L);
DFT(X),DFT(Y);
for(int i=0;i<L;++i)X[i]=1ll*Y[i]*(P+2-1ll*X[i]*Y[i]%P)%P;
IDFT(X),X.resize(l);
copy(X.begin(),X.begin()+l,I.begin());
}
return I.resize(n),I;
}
Vec fix(Vec A,int n)
{
return A.resize(n),A;
}
Vec der(Vec A,bool mod=1)
{
int n=A.size();
if(n==1)return Vec(1,0);
Vec D(n-1);
for(int i=1;i<n;++i)D[i-1]=1ll*i*A[i]%P;
if(mod)D.resize(n);
return D;
}
Vec inte(Vec A,bool mod=1)
{
int n=A.size();
Vec I=Vec(n+1,0);
for(int i=1;i<=n;++i)I[i]=1ll*inv(i)*A[i-1]%P;
if(mod)I.resize(n);
return I;
}
inline Vec ln(Vec A){
assert(A[0]==1);
int n=A.size();
return inte(fix(der(A)*~A,n));
}
inline Vec sqrt(Vec A)
{
int n=A.size(),N=extend(n);
A.resize(N);
Vec R(N);
R[0]=degree(A[0],2,P);
int i2=inv(2,P);
for(int l=2;l<=N;l<<=1)
{
Vec F(l),G(l);
copy(A.begin(),A.begin()+l,F.begin());
copy(R.begin(),R.begin()+l,G.begin());
Vec I=~G;
int L=l<<1;
F.resize(L),G.resize(L),I.resize(L);
DFT(F),DFT(G),DFT(I);
for(int i=0;i<L;++i)G[i]=1ll*G[i]*G[i]%P,F[i]=1ll*(F[i]+G[i])*i2%P*I[i]%P;
IDFT(F),F.resize(l);
copy(F.begin(),F.begin()+l,R.begin());
}
return R.resize(n),R;
}
inline Vec exp(Vec A)
{
assert(!A[0]);
int n=A.size(),N=extend(n);
A.resize(N);
Vec E(N,0);
E[0]=1;
for(int l=2;l<=N;l<<=1)
{
Vec P=(fix(A,l)-ln(fix(E,l))+1) * fix(E,l);
copy(P.begin(),P.begin()+l,E.begin());
}
return E.resize(n),E;
}
Vec ls,rs,pos;
vector<Vec>h,g;
int id;
#define mid ((l+r)>>1)
inline void dfs(int &rt,int l,int r){
rt=id++;
if(l==r)return pos[l]=rt,void();
dfs(ls[rt],l,mid),dfs(rs[rt],mid+1,r);
}
#undef mid
inline void build(int n){
ls.resize(2*n),rs.resize(2*n);
h.resize(2*n),g.resize(2*n);
pos.resize(n),id=0;
dfs(*new int,0,n-1);
}
pair<Vec,Vec> calc(Vec H,Vec G1,Vec G2){
int n=H.size(),N=extend(n),m1=G1.size(),m2=G2.size();
reverse(G1.begin(),G1.end());
reverse(G2.begin(),G2.end());
H.resize(N),G1.resize(N),G2.resize(N);
DFT(H),DFT(G1),DFT(G2);
for(int i=0;i<N;++i)G1[i]=1ll*G1[i]*H[i]%P;
for(int i=0;i<N;++i)G2[i]=1ll*G2[i]*H[i]%P;
IDFT(G1),IDFT(G2);
return make_pair(Vec(G2.begin()+m2-1,G2.begin()+n),Vec(G1.begin()+m1-1,G1.begin()+n));
}
Vec _eval(Vec A,Vec Q){
int n=A.size(),N=extend(2*n-2);
build(n);
for(int i=0;i<n;++i)g[pos[i]]=(Vec){1,add(P-Q[i])};
for(int i=n*2-2;~i;--i)if(ls[i])g[i]=g[ls[i]]*g[rs[i]];
g[0]=~g[0];
reverse(g[0].begin(),g[0].end());
A.resize(N),g[0].resize(N);
DFT(A),DFT(g[0]);
for(int i=0;i<N;++i)A[i]=1ll*A[i]*g[0][i]%P;
IDFT(A);
h[0].resize(n);
copy(A.begin()+n,A.begin()+2*n,h[0].data());
for(int i=0;i<n*2-1;++i)if(ls[i])tie(h[ls[i]],h[rs[i]])=calc(h[i],g[ls[i]],g[rs[i]]);
Vec ans(n);
for(int i=0;i<n;++i)ans[i]=h[pos[i]][0];
return ans;
}
Vec eval(Vec A,Vec Q)
{
ls.clear(),rs.clear(),pos.clear(),h.clear(),g.clear();
int n=A.size(),m=Q.size();
A.resize(max(n,m)),Q.resize(max(n,m));
return fix(_eval(A,Q),m);
}
#endif
}
using namespace Poly;