多项式
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define rev(a,n) reverse(a,a+n)
#define bceil(n) (1<<32-__builtin_clz(n-1))
using namespace std;
const int siz=1<<18;char buf[siz],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,siz,stdin),p1==p2)?EOF:*p1++
int read(){
int a=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+(ch^'0'),ch=getchar();
return a;
}
void write(int a){
if(a>9) write(a/10);putchar(a%10+'0');
}
const int MAXN=1e6+10,P=998244353,Img=86583718;
int l,_lg_l,r[MAXN],inv[MAXN],sav[MAXN<<1],Wn[MAXN<<1];
ll qpow(ll a,ll b=P-2){
if(a==1) return 1;ll ans=1;
while(b){if(b&1) ans=ans*a%P;a=a*a%P;b>>=1;}
return ans;
}void Init(int lim){
l=bceil(lim),_lg_l=__builtin_clz(l);int W=qpow(3,(P-1)/l);Wn[l>>1]=1;
for(int i=0;i<l;i++) r[i]=(r[i>>1]>>1)|((i&1)?l>>1:0);
for(int i=(l>>1)+1;i<l;i++) Wn[i]=1ll*Wn[i-1]*W%P;
for(int i=(l>>1)-1;i;i--) Wn[i]=Wn[i<<1];
}
void px(int *A,int *B,int n){for(int i=0;i<n;i++) A[i]=1ll*A[i]*B[i]%P;}
void NTT(int *A,int lim,int type){
static ull f[MAXN<<1];if(type-1) rev(A+1,lim-1);
for(int i=0,u=__builtin_clz(lim)-_lg_l;i<lim;i++) f[i]=A[r[i]>>u];
for(int mid=1;mid<lim;mid<<=1){
for(int j=0;j<lim;j+=mid+mid){
for(int k=0,x;k<mid;k++)
x=Wn[mid+k]*f[j|mid|k]%P,f[j|mid|k]=f[j|k]+P-x,f[j|k]+=x;
}if(mid==(1<<10)){for(int i=0;i<lim;i++) f[i]%=P;}
}if(type-1){
ull inv=P-(P-1)/lim;for(int i=0;i<lim;i++) A[i]=f[i]%P*inv%P;
}else for(int i=0;i<lim;i++) A[i]=f[i]%P;
}
void mul(int *A,int *B,int la,int lb){
int lim=bceil(la+la);cpy(sav,B,la);
NTT(A,lim,1);NTT(sav,lim,1);px(A,sav,lim);NTT(A,lim,-1);
clr(A+lb,lim-lb);clr(sav,lim);
}
void invp(int *A,int lim){
int n=bceil(lim);static int w[MAXN<<1],r[MAXN<<1];w[0]=qpow(A[0]);
for(int ln=2;ln<=n;ln<<=1){
cpy(r,w,ln>>1);cpy(sav,A,ln);
NTT(sav,ln,1);NTT(r,ln,1);px(r,sav,ln);NTT(r,ln,-1);clr(r,ln>>1);
cpy(sav,w,ln);NTT(sav,ln,1);NTT(r,ln,1);px(r,sav,ln);NTT(r,ln,-1);
for(int i=ln>>1;i<ln;i++) w[i]=(w[i]*2ll-r[i]+P)%P;
}cpy(A,w,lim);clr(sav,n);clr(w,n);clr(r,n);
}
void mof(int *A,int *B,int n,int m){
static int q[MAXN<<1],t[MAXN<<1],_s[MAXN];
int l=n-m+1;cpy(_s,B,m);rev(B,m);cpy(q,B,l);rev(B,m);
rev(A,n);cpy(t,A,l);rev(A,n);invp(q,l);
mul(q,t,l,l);rev(q,l);mul(B,q,n,n);
for(int i=0;i<m-1;i++) A[i]=(A[i]-B[i]+P)%P;
cpy(B,_s,m);clr(B+m,n-m);clr(A+m-1,n-m+1);
clr(q,n);clr(t,n);
}//A<-A%B.
void deriv(int *A,int lim){
for(int i=1;i<lim;i++) A[i-1]=1ll*A[i]*i%P;A[lim-1]=0;
}void inv_init(int lim){
inv[1]=1;for(int i=2;i<=lim;i++) inv[i]=1ll*inv[P%i]*(P-P/i)%P;
}void integ(int *A,int lim){
for(int i=lim;i;i--) A[i]=1ll*A[i-1]*inv[i]%P;A[0]=0;
}
void lnp(int *A,int lim){
static int w[MAXN<<1];cpy(w,A,lim);
invp(w,lim);deriv(A,lim);mul(A,w,lim,lim);
integ(A,lim-1);clr(w,lim);
}
void exp(int *A,int lim){
static int s[MAXN<<1],s2[MAXN<<1];int n=bceil(lim);s2[0]=1;
for(int ln=2;ln<=n;ln<<=1){
cpy(s,s2,ln>>1);lnp(s,ln);
for(int i=0;i<ln;i++) s[i]=(A[i]-s[i]+P)%P;
s[0]=(s[0]+1)%P;mul(s2,s,ln,ln);
}cpy(A,s2,lim);clr(s,n);clr(s2,n);
}
void power(int *A,int lim,ll k){
int a,inv,t=0;
while(A[t]==0) t++;a=qpow(A[t],k);inv=qpow(A[t]);
if(t*k>lim){clr(A,lim);return;}
for(int i=0;i+t<lim;i++) A[i]=1ll*A[i+t]*inv%P;
lnp(A,lim);for(int i=0;i<lim;i++) A[i]=1ll*A[i]*k%P;exp(A,lim);
for(int i=lim-1-t*k;i>=0;i--) A[i+t*k]=1ll*A[i]*a%P;clr(A,t*k);
}
void mod_power(int *f,int *g,int n,int m,int k){
static int ans[MAXN];ans[0]=1;int ln=1;
if(n>=m){mof(f,g,n,m);n=m-1;}
while(k){if(k&1){
mul(ans,f,max(ln,n),ln+n-1);ln+=n-1;
if(ln>=m){mof(ans,g,ln,m);ln=m-1;}
}mul(f,f,n,(n<<1)-1);n+=n-1;
if(n>=m){mof(f,g,n,m);n=m-1;}k>>=1;
}cpy(f,ans,ln);clr(ans,ln);
}
int sq;random_device rd;mt19937 rnd(rd());
struct Complex{
ll Re,Im;Complex(ll a=0,ll b=0){Re=a,Im=b;}
const Complex operator*(const Complex a)const{
return Complex((Re*a.Re%P+Im*a.Im%P*sq%P)%P,(Re*a.Im%P+Im*a.Re%P)%P);
}
};
int Cipolla(int n){
if(!n) return 0;n%=P;
if(qpow(n,P-1>>1)==P-1) return -1;
ll a;while(1){
a=rnd()%P;sq=(a*a%P-n+P)%P;if(qpow(sq,P-1>>1)==P-1) break;
}Complex ans(1),k(a,1);int b=P+1>>1;
while(b){if(b&1) ans=ans*k;k=k*k;b>>=1;}
return ans.Re;
}
void sqrt(int *A,int lim){
int n=bceil(lim);
static int s[MAXN<<1],s2[MAXN<<1];
if(A[0]==1) s[0]=1;
else{s[0]=Cipolla(A[0]);s[0]=P-s[0]<s[0]?P-s[0]:s[0];}
for(int ln=2;ln<=n;ln<<=1){
for(int i=0;i<(ln>>1);i++) s2[i]=(s[i]<<1)%P;
invp(s2,ln);NTT(s,ln,1);px(s,s,ln);NTT(s,ln,-1);
for(int i=0;i<ln;i++) s[i]=(A[i]+s[i])%P;mul(s,s2,ln,ln);
}cpy(A,s,lim);clr(s,n+n);clr(s2,n+n);
}
void cos(int *A,int lim){
static int S[MAXN];int inv=qpow(2);
for(int i=0;i<lim;i++) A[i]=1ll*A[i]*Img%P;
exp(A,lim);cpy(S,A,lim);invp(S,lim);
for(int i=0;i<lim;i++) A[i]=1ll*(A[i]+S[i])%P*inv%P;
}
void sin(int *A,int lim){
static int S[MAXN];int inv=qpow(Img<<1);
for(int i=0;i<lim;i++) A[i]=1ll*A[i]*Img%P;
exp(A,lim);cpy(S,A,lim);invp(S,lim);
for(int i=0;i<lim;i++) A[i]=1ll*(A[i]-S[i]+P)%P*inv%P;
}
void arcsin(int *A,int lim){
static int S[MAXN];cpy(S,A,lim);deriv(S,lim);
int n=bceil(lim*2);
NTT(A,n,1);px(A,A,n);NTT(A,n,-1);clr(A+lim,n-lim);
for(int i=0;i<lim;i++) A[i]=(P-A[i])%P;
A[0]=(A[0]+1)%P;sqrt(A,lim);invp(A,lim);
mul(A,S,lim,lim);integ(A,lim);clr(S,lim);
}
void arctan(int *A,int lim){
static int S[MAXN];cpy(S,A,lim);deriv(S,lim);
int n=bceil(lim*2);
NTT(A,n,1);px(A,A,n);NTT(A,n,-1);clr(A+lim,n-lim);
A[0]=(A[0]+1)%P;invp(A,lim);
mul(A,S,lim,lim);integ(A,lim);clr(S,lim);
}
int Fac[MAXN],
[MAXN];
void Fac_init(int lim){
Fac[0]=iFac[0]=1;
for(int i=1;i<=lim;i++) Fac[i]=1ll*Fac[i-1]*i%P,iFac[i]=1ll*iFac[i-1]*inv[i]%P;
}
void mulT(int *A,int *B,int lim){
rev(B,lim);mul(A,B,lim,lim+lim);
for(int i=0;i<lim;i++) A[i]=A[lim+i-1];
clr(A+lim,lim);rev(B,lim);
}
void trans(int *A,int lim,int k){
static int g[MAXN];g[0]=1;
for(int i=1;i<lim;i++) g[i]=1ll*g[i-1]*k%P,A[i]=1ll*A[i]*Fac[i]%P;
for(int i=1;i<lim;i++) g[i]=1ll*g[i]*iFac[i]%P;mulT(A,g,lim);
for(int i=0;i<lim;i++) A[i]=1ll*A[i]*iFac[i]%P;clr(g,lim);
}
void Stirling(int *A,int lim,int type,int r_c,int k=0){
static int f[MAXN];lim++;
if(type==1&&r_c==1){
int b[20],tot=0,ln=--lim;while(ln) b[++tot]=ln,ln>>=1;
ln=A[1]=b[tot--];while(tot--){
cpy(f,A,ln+1);trans(f,ln+1,ln);mul(A,f,ln+1,(ln<<1)+1);
ln<<=1;if(ln==b[tot+1]) continue;A[ln+1]=A[ln];
for(int i=ln;i;i--) A[i]=(1ll*A[i]*ln%P+A[i-1])%P;A[0]=1ll*A[0]*ln%P;
ln++;
}clr(f,lim+1);
}else if(type==2&&r_c==1){
for(int i=0;i<lim;i++) A[i]=qpow(i,lim-1)*iFac[i]%P,f[i]=(i&1?P-1ll:1ll)*iFac[i]%P;
mul(A,f,lim,lim);clr(f,lim);
}else{
cpy(A,(type==1?inv:iFac)+1,lim-1);
lnp(A,lim);for(int i=0;i<lim;i++) A[i]=1ll*A[i]*k%P;exp(A,lim);
for(int i=lim-1;i>=k;i--) A[i]=A[i-k];clr(A,k);
for(int i=0;i<lim;i++) A[i]=1ll*A[i]*iFac[k]%P*Fac[i]%P;
}
}
int *p[MAXN],*q[MAXN],tmp[MAXN<<5],*now=tmp;
void Mp_build(int id,int l,int r,int *a){
q[id]=now,now+=r-l+2,p[id]=now,now+=r-l+2;
if(l==r) return q[id][0]=1,q[id][1]=(P-a[l])%P,void();
static int s[MAXN];int mid=l+r>>1;
Mp_build(id<<1,l,mid,a);Mp_build(id<<1|1,mid+1,r,a);
cpy(s,q[id<<1|1],r-mid+1);mul(s,q[id<<1],mid-l+2,r-l+2);
cpy(q[id],s,r-l+2);clr(s,r-l+2);
}
void Mp_solve(int id,int l,int r,int *a){
if(l==r) return a[l]=p[id][0],void();
static int s[MAXN];int mid=l+r>>1;
cpy(s,p[id],r-l+1);mulT(s,q[id<<1|1],r-mid+1);cpy(p[id<<1],s,mid-l+1);
cpy(s,p[id],r-l+1);mulT(s,q[id<<1],mid-l+2);cpy(p[id<<1|1],s,r-mid);
Mp_solve(id<<1,l,mid,a);Mp_solve(id<<1|1,mid+1,r,a);clr(s,r-l+1);
}
void Multipoint(int *f,int *a,int n){
static int c[MAXN],F[MAXN];cpy(F,f,n);
Mp_build(1,0,n-1,a);cpy(c,q[1],n);invp(c,n);
mulT(F,c,n);cpy(p[1],F+1,n-1);Mp_solve(1,0,n-1,c);
for(int i=0;i<n;i++) a[i]=(1ll*a[i]*c[i]%P+f[0])%P;
clr(c,n);clr(F,n);now=tmp;
}
int *G[MAXN],*H[MAXN],Tmp[MAXN<<5],*Now=Tmp;
void Inter_build(int id,int l,int r,int *x){
G[id]=Now,Now+=r-l+2,H[id]=Now,Now+=r-l+2;
if(l==r) return G[id][0]=(P-x[l])%P,G[id][1]=1,void();
static int s[MAXN];int mid=l+r>>1;
Inter_build(id<<1,l,mid,x);Inter_build(id<<1|1,mid+1,r,x);
cpy(s,G[id<<1|1],r-mid+1);mul(s,G[id<<1],mid-l+2,r-l+2);
cpy(G[id],s,r-l+2);clr(s,r-l+2);
}
void Inter_solve(int id,int l,int r,int *y){
if(l==r) return H[id][0]=y[l],void();
static int s1[MAXN],s2[MAXN];int mid=l+r>>1;
Inter_solve(id<<1,l,mid,y);Inter_solve(id<<1|1,mid+1,r,y);
cpy(s1,H[id<<1],mid-l+1);mul(s1,G[id<<1|1],r-mid+1,r-l+1);
cpy(s2,H[id<<1|1],r-mid);mul(s2,G[id<<1],mid-l+2,r-l+1);
for(int i=0;i<r-l+1;i++) H[id][i]=(s1[i]+s2[i])%P;
clr(s1,r-l+1);clr(s2,r-l+1);
}
void Interpolation(int *f,int *x,int *y,int n){
Inter_build(1,0,n-1,x);cpy(f,G[1],n+1);deriv(f,n+1);
Multipoint(f,x,n);for(int i=0;i<n;i++) y[i]=1ll*y[i]*qpow(x[i])%P;
Inter_solve(1,0,n-1,y);cpy(f,H[1],n);Now=Tmp;
}
int Bostan_mori(int *f,int *g,int n,int k){
static int s[MAXN];for(;k;k>>=1){
cpy(s,g,n);for(int i=1;i<n;i+=2) s[i]=(P-s[i])%P;
mul(f,s,n,n<<1);mul(g,s,n,n<<1);clr(s,n);
for(int i=k&1;i<n<<1;i+=2) f[i>>1]=f[i];
for(int i=0;i<n<<1;i+=2) g[i>>1]=g[i];
clr(f+n,n);clr(g+n,n);
}return f[0]*qpow(g[0])%P;
}
int LSB_first(int *f,int *a,int n,int k){
mul(a,f,k+1,k);return Bostan_mori(a,f,k+1,n);
}
void comp(int *A,int *B,int n,int m){
int L=sqrt(n)+1,lim=bceil(n+n);
static int B1[210][MAXN],B2[210][MAXN],R[MAXN],C[MAXN];
B1[0][0]=B2[0][0]=1;cpy(B1[1],B,m);NTT(B,lim,1);
for(int i=2;i<=L;i++){
int *Bp=B1[i-1],*Bn=B1[i];NTT(Bp,lim,1);
for(int j=0;j<lim;j++) Bn[j]=1ll*B[j]*Bp[j]%P;
NTT(Bp,lim,-1);NTT(Bn,lim,-1);clr(Bn+n,lim-n);
}cpy(B2[1],B1[L],n);int *Bl=B1[L];NTT(Bl,lim,1);
for(int i=2;i<L;i++){
int *Bp=B2[i-1],*Bn=B2[i];NTT(Bp,lim,1);
for(int j=0;j<lim;j++) Bn[j]=1ll*Bl[j]*Bp[j]%P;
NTT(Bp,lim,-1);NTT(Bn,lim,-1);clr(Bn+n,lim-n);
}NTT(Bl,lim,-1);
for(int i=0;i<L;i++){
clr(C,lim);
for(int j=0;j<L;j++)for(int k=0;k<n;k++) C[k]=(C[k]+1ll*A[i*L+j]*B1[j][k])%P;
NTT(C,lim,1);NTT(B2[i],lim,1);for(int j=0;j<lim;j++) C[j]=1ll*C[j]*B2[i][j]%P;
NTT(C,lim,-1);for(int i=0;i<n;i++) R[i]=(R[i]+C[i])%P;
}cpy(A,R,n);//NTT(B,lim,-1);clr(B+m,lim-m);
}
void print(int *A,int lim){
for(int i=0;i<lim;i++) write(A[i]),putchar(' ');
putchar('\n');
}
// void comp_inv(int *A,int n){
// int L=sqrt(n)+1,lim=bceil(n+n);invp(A,n);
// static int B1[210][MAXN],B2[210][MAXN];
// B1[0][0]=B2[0][0]=1;NTT(B1[0],lim,1);cpy(B2[0],B1[0],lim);
// cpy(B1[1],A,n);NTT(B1[1],lim,1);
// for(int i=2;i<=L;i++){
// int *Bp=B1[i-1],*Bn=B1[i];NTT(Bp,lim,1);
// for(int j=0;j<lim;j++) Bn[j]=1ll*B1[1][j]*Bp[j]%P;
// NTT(Bp,lim,-1);NTT(Bn,lim,-1);clr(Bn+n,lim-n);
// }cpy(B2[1],B1[L],n);int *Bl=B1[L];NTT(Bl,lim,1);
// for(int i=2;i<L;i++){
// int *Bp=B2[i-1],*Bn=B2[i];NTT(Bp,lim,1);
// for(int j=0;j<lim;j++) Bn[j]=1ll*Bl[j]*Bp[j]%P;
// NTT(Bp,lim,-1);NTT(Bn,lim,-1);clr(Bn+n,lim-n);
// }NTT(Bl,lim,-1);
// for(int i=0;i<=L;i++) print(B1[i],n);
// for(int i=0;i<L;i++) print(B2[i],n);
// clr(A,n);
// for(int i=0;i<L;i++) for(int j=0;j<L;j++){
// int x=i*L+j;if(x>=n) return; for(int k=0;k<=x;k++)
// A[x+1]=(A[x+1]+1ll*B2[i][k]*B1[j][k]%P)%P;
// A[x+1]=qpow(x+1)*A[x+1]%P;
// }
// }//
int n,m,a[MAXN],b[MAXN];
int main(){
n=read();Init(n<<1);inv_init(n);
return 0;
}
vector
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define rev(a,n) reverse(a,a+n)
#define bceil(n) (1<<32-__builtin_clz(n-1))
using namespace std;
const int Siz=1<<18;char buf[Siz],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Siz,stdin),p1==p2)?EOF:*p1++
int read(){
int a=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+(ch^'0'),ch=getchar();
return a;
}
void write(int a){
if(a>9) write(a/10);putchar(a%10+'0');
}
const int MAXN=1e7+10,P=998244353,Img=86583718;
int l,_lg_l,r[MAXN],inv[MAXN],Fac[MAXN],iFac[MAXN],Wn[MAXN<<1];
ll qpow(ll a,ll b=P-2){
if(a==1) return 1;ll ans=1;
while(b){if(b&1) ans=ans*a%P;a=a*a%P;b>>=1;}
return ans;
}void Init(int lim){
l=bceil(lim),_lg_l=__builtin_clz(l);int W=qpow(3,(P-1)/l);Wn[l>>1]=1;
for(int i=0;i<l;i++) r[i]=(r[i>>1]>>1)|((i&1)?l>>1:0);
for(int i=(l>>1)+1;i<l;i++) Wn[i]=1ll*Wn[i-1]*W%P;
for(int i=(l>>1)-1;i;i--) Wn[i]=Wn[i<<1];
}
void inv_init(int lim){
inv[1]=1;for(int i=2;i<=lim;i++) inv[i]=1ll*inv[P%i]*(P-P/i)%P;
}
void Fac_init(int lim){
Fac[0]=iFac[0]=1;
for(int i=1;i<=lim;i++) Fac[i]=1ll*Fac[i-1]*i%P,iFac[i]=1ll*iFac[i-1]*inv[i]%P;
}
void NTT(int *A,int lim,int type){
static ull f[MAXN<<1];if(type-1) rev(A+1,lim-1);
for(int i=0,u=__builtin_clz(lim)-_lg_l;i<lim;i++) f[i]=A[r[i]>>u];
for(int mid=1;mid<lim;mid<<=1){
for(int j=0;j<lim;j+=mid+mid){
for(int k=0,x;k<mid;k++)
x=Wn[mid+k]*f[j|mid|k]%P,f[j|mid|k]=f[j|k]+P-x,f[j|k]+=x;
}if(mid==(1<<10)){for(int i=0;i<lim;i++) f[i]%=P;}
}if(type-1){
ull inv=P-(P-1)/lim;for(int i=0;i<lim;i++) A[i]=f[i]%P*inv%P;
}else for(int i=0;i<lim;i++) A[i]=f[i]%P;
}
int sq;random_device rd;mt19937 rnd(rd());
struct Complex{
ll Re,Im;Complex(ll a=0,ll b=0){Re=a,Im=b;}
const Complex operator*(const Complex a)const{
return Complex((Re*a.Re%P+Im*a.Im%P*sq%P)%P,(Re*a.Im%P+Im*a.Re%P)%P);
}
};
int Cipolla(int n){
if(!n) return 0;n%=P;
if(qpow(n,P-1>>1)==P-1) return -1;
ll a;while(1){
a=rnd()%P;sq=(a*a%P-n+P)%P;if(qpow(sq,P-1>>1)==P-1) break;
}Complex ans(1),k(a,1);int b=P+1>>1;
while(b){if(b&1) ans=ans*k;k=k*k;b>>=1;}
return ans.Re;
}
struct Poly{
vector<int>a;int operator[](int k)const{return k<a.size()?a[k]:0;}
int &operator[](int k){if(k>=a.size())a.resize(k+1);return a[k];}
int *data(){return a.data();}const int *data()const{return a.data();}
Poly(){}Poly(vector<int>b):a(b){};Poly(int *A,int lim){
a.resize(lim);cpy(a.data(),A,lim);
}Poly(int i){a.resize(1);a[0]=i;}
int size()const{return a.size();}void resize(int k){a.resize(k);}
Poly slice(int k)const{
if(k<=a.size()) return vector<int>(a.begin(),a.begin()+k);
vector<int>b(a);b.resize(k);return b;
}
void print(){for(int i:a) write(i),putchar(' ');putchar('\n');}
Poly operator+(const int k)const{vector<int>b(a);b[0]=(b[0]+k)%P;return b;}
Poly operator-(const int k)const{vector<int>b(a);b[0]=(b[0]+P-k)%P;return b;}
Poly operator*(const int k)const{
if(k==1) return a;vector<int>b(a.size());if(!k) return b;
for(int i=0;i<a.size();i++) b[i]=1ll*a[i]*k%P;return b;
}
Poly operator+(const Poly b)const{
vector<int>v(max(int(a.size()),b.size()));
for(int i=0;i<v.size();i++) v[i]=(a[i]+b[i])%P;
return v;
}
Poly operator-()const{
vector<int>b(a.size());for(int i=0;i<a.size();i++) b[i]=a[i]?P-a[i]:0;return b;
}
Poly operator-(const Poly b)const{return operator+(-b);}
Poly operator*(const Poly b)const{
if(size()+b.size()-1<=64||size()<=16||b.size()<=16){
vector<int>f(size()+b.size()-1);
for(int i=0;i<size();i++) for(int j=0;j<b.size();j++)
f[i+j]=(f[i+j]+1ll*a[i]*b[j]%P)%P;
return f;
}
int lim=bceil(size()+b.size()-1);vector<int>f(lim),g(lim);
cpy(f.data(),data(),size());cpy(g.data(),b.data(),b.size());
NTT(f.data(),lim,1);NTT(g.data(),lim,1);
for(int i=0;i<lim;i++) f[i]=1ll*f[i]*g[i]%P;
NTT(f.data(),lim,-1);f.resize(size()+b.size()-1);return f;
}
Poly mul(const Poly b,int n)const{
if(n<=32){
vector<int>f(n);
for(int i=0;i<min(n,size());i++) for(int j=0;j<min(n-i,b.size());j++)
f[i+j]=(f[i+j]+1ll*a[i]*b[j]%P)%P;
return f;
}
int lim=bceil((n<<1)-1);vector<int>f(lim),g(lim);
cpy(f.data(),data(),min(size(),n));cpy(g.data(),b.data(),min(b.size(),n));
NTT(f.data(),lim,1);NTT(g.data(),lim,1);
for(int i=0;i<lim;i++) f[i]=1ll*f[i]*g[i]%P;
NTT(f.data(),lim,-1);f.resize(n);return f;
}
Poly pow2()const{
int lim=bceil((size()<<1)-1);vector<int>f(lim);
cpy(f.data(),data(),size());NTT(f.data(),lim,1);
for(int i=0;i<lim;i++) f[i]=1ll*f[i]*f[i]%P;
NTT(f.data(),lim,-1);f.resize((size()<<1)-1);return f;
}
Poly invp()const{
int n=bceil(size());Poly w,v;w.a.push_back(qpow(a[0]));vector<int>f(n);v.resize(n);
for(int ln=2;ln<=n;ln<<=1){
cpy(v.data(),data(),ln);cpy(f.data(),w.data(),ln>>1);
NTT(v.data(),ln,1);NTT(f.data(),ln,1);
for(int i=0;i<ln;i++) v[i]=1ll*v[i]*f[i]%P;NTT(v.data(),ln,-1);clr(v.data(),ln>>1);
w.resize(ln);cpy(f.data(),w.data(),ln);NTT(v.data(),ln,1);NTT(f.data(),ln,1);
for(int i=0;i<ln;i++) v[i]=1ll*v[i]*f[i]%P;NTT(v.data(),ln,-1);
for(int i=ln>>1;i<ln;i++) w[i]=(w[i]*2ll-v[i]+P)%P;
}w.resize(size());return w;
}
Poly operator%(const Poly b)const{
int l=size()-b.size()+1;vector<int>f(a.end()-l,a.end()),g(b.a);
rev(f.begin(),l);rev(g.begin(),g.size());g.resize(l);
Poly k=Poly(g).invp()*Poly(f);k.resize(l);rev(k.a.begin(),l);
return slice(b.size()-1)-k.mul(b,b.size()-1);
}
Poly deriv()const{
vector<int>b(size()-1);for(int i=1;i<size();i++) b[i-1]=1ll*a[i]*i%P;return b;
}Poly integ(int k=0)const{
vector<int>b(size()+1);b[0]=k;for(int i=1;i<=size();i++) b[i]=1ll*a[i-1]*inv[i]%P;return b;
}
Poly ln()const{return invp().mul(deriv(),size()-1).integ();}
Poly exp()const{
int n=bceil(size());Poly w(1),v;w.resize(2);
for(int ln=2;ln<=n;ln<<=1) v=slice(ln)-w.ln(),v[0]++,w=w*v,w.a.push_back(0);
w.resize(size());return w;
}
Poly sqrt()const{
int n=bceil(size());Poly w(1);if(a[0]!=1) w[0]=Cipolla(a[0]),w[0]=min(w[0],P-w[0]);
for(int ln=2;ln<=n;ln<<=1) w.resize(ln),w=(mul(w.invp(),ln)+w)*(P-(P>>1));
w.resize(size());return w;
}
Poly sin()const{Poly a=(operator*(Img)).exp();return (a-a.invp())*qpow(Img<<1)%P;}
Poly cos()const{Poly a=(operator*(Img)).exp();return (a+a.invp())*inv[2]%P;}
Poly arcsin()const{return deriv().mul((-pow2().slice(size())+1).sqrt().invp(),size()-1).integ();}
Poly arctan()const{return deriv().mul((pow2().slice(size())+1).invp(),size()-1).integ();}
Poly mulT(const Poly b)const{
Poly w=b;reverse(w.a.begin(),w.a.end());w=(*this)*w;
return vector<int>(w.a.begin()+b.size()-1,w.a.begin()+a.size()+b.size()-1);
}
Poly trans(int c)const{
Poly f,g;f.resize(size()),g.resize(size());f[0]=a[0],g[0]=1;
for(int i=1;i<size();i++) g[i]=1ll*g[i-1]*c%P,f[i]=1ll*a[i]*Fac[i]%P;
for(int i=0;i<size();i++) g[i]=1ll*g[i]*iFac[i]%P;f=f.mulT(g);
for(int i=0;i<size();i++) f[i]=1ll*f[i]*iFac[i]%P;return f;
}
Poly Multipoint(const Poly a)const;
Poly compinv()const;
};
Poly Zero(int k){return vector<int>(k,0);}
Poly Polyread(int n){Poly b;b.resize(n);for(int i=0;i<n;i++) b[i]=read();return b;}
Poly Stirling(int type,int r_c,int n,int k=0){
Poly f;if(type==1&&r_c==1){//[n,i]
int d[20],tot=0,ln=n;while(ln) d[++tot]=ln,ln>>=1;
ln=f[1]=d[tot--];while(tot--){
f=f*f.trans(ln);ln<<=1;if(ln==d[tot+1]) continue;f.a.push_back(f[ln]);
for(int i=ln;i;i--) f[i]=(1ll*f[i]*ln%P+f[i-1])%P;f[0]=1ll*f[0]*(ln++)%P;
}return f;
}else if(type==2&&r_c==1){//{n,i}
Poly g(vector<int>(iFac,iFac+n+1));for(int i=1;i<=n;i+=2) g[i]=g[i]?P-g[i]:0;
f.resize(n+1);for(int i=0;i<=n;i++) f[i]=qpow(i,n)*iFac[i]%P;return f.mul(g,n+1);
}else{//[i,k],{i,k}
f.resize(n+1);cpy(f.data(),(type==1?inv:iFac)+1,n);f=(f.ln()*k).exp();
for(int i=n;i>=k;i--) f[i]=1ll*f[i-k]*iFac[k]%P*Fac[i]%P;
clr(f.data(),k);return f;
}
}
#define Polyv vector<Poly>
Polyv Q,Q2;
void Multi_build(int id,int l,int r,int *a){
if(l==r) return Q[id]=vector<int>({1,a[l]?P-a[l]:0}),void();
int mid=l+r>>1;Multi_build(id<<1,l,mid,a);Multi_build(id<<1|1,mid+1,r,a);
Q[id]=Q[id<<1]*Q[id<<1|1];
}
void Multi_solve(int id,int l,int r,Poly a,Poly &w){
a.resize(r-l+1);if(l==r) return w[l]=a[0],void();int mid=l+r>>1;
Multi_solve(id<<1,l,mid,a.mulT(Q[id<<1|1]),w);
Multi_solve(id<<1|1,mid+1,r,a.mulT(Q[id<<1]),w);
}
Poly Poly::Multipoint(const Poly a)const{
int n=max(a.size(),size());Q.resize(n<<2);Multi_build(1,0,n-1,a.slice(n).data());
Poly w;w.resize(n);
Multi_solve(1,0,n-1,slice(n).mulT(Q[1].invp()),w);w.resize(a.size());return w;
}
void Inter_build(int id,int l,int r,const int *x){
if(l==r) return Q2[id].resize(2),Q2[id][0]=(x[l]?P-x[l]:0),Q2[id][1]=1,void();
int mid=l+r>>1;Inter_build(id<<1,l,mid,x);Inter_build(id<<1|1,mid+1,r,x);
Q2[id]=Q2[id<<1]*Q2[id<<1|1];
}
Poly Inter_solve(int id,int l,int r,int *y){
if(l==r) return Poly(y[l]);int mid=l+r>>1;
return Inter_solve(id<<1,l,mid,y)*Q2[id<<1|1]+Inter_solve(id<<1|1,mid+1,r,y)*Q2[id<<1];
}
Poly Interpolation(const Poly x,const Poly y){
int n=x.size();Q2.resize(n<<2);Inter_build(1,0,n-1,x.data());Poly w=Q2[1].deriv().Multipoint(x);
for(int i=0;i<n;i++) w[i]=1ll*y[i]*qpow(w[i])%P;return Inter_solve(1,0,n-1,w.data());
}
int n;Poly a;
int main(){
n=read();Init(n<<1);
return 0;
}
下降幂多项式
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define rev(a,n) reverse(a,a+n)
#define bceil(n) (1<<__lg(n-1)+1)
using namespace std;
int read(){
int a=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+(ch^'0'),ch=getchar();
return a;
}
void write(int a){
if(a>9) write(a/10);putchar(a%10+'0');
}
const int MAXN=1e6+10,P=998244353,G=3,Img=86583718;
int l,_lg_l,r[MAXN],inv[MAXN],sav[MAXN<<1],Wn[MAXN<<1];
ll qpow(ll a,ll b=P-2){
if(a==1) return 1;ll ans=1;
while(b){if(b&1) ans=ans*a%P;a=a*a%P;b>>=1;}
return ans;
}
void Init(int lim){
l=bceil(lim),_lg_l=__builtin_clz(l);int W=qpow(G,(P-1)/l);Wn[l>>1]=1;
for(int i=0;i<l;i++) r[i]=(r[i>>1]>>1)|((i&1)?l>>1:0);
for(int i=(l>>1)+1;i<l;i++) Wn[i]=1ll*Wn[i-1]*W%P;
for(int i=(l>>1)-1;i;i--) Wn[i]=Wn[i<<1];
}
void px(int *A,int *B,int n){for(int i=0;i<n;i++) A[i]=1ll*A[i]*B[i]%P;}
void NTT(int *A,int lim,int type){
static ull f[MAXN<<1];if(type-1) rev(A+1,lim-1);
for(int i=0,u=__builtin_clz(lim)-_lg_l;i<lim;i++) f[i]=A[r[i]>>u];
for(int mid=1;mid<lim;mid<<=1){
for(int j=0;j<lim;j+=mid+mid){
for(int k=0,x;k<mid;k++)
x=Wn[mid+k]*f[j|mid|k]%P,f[j|mid|k]=f[j|k]+P-x,f[j|k]+=x;
}if(mid==(1<<10)){for(int i=0;i<lim;i++) f[i]%=P;}
}if(type-1){
ull inv=P-(P-1)/lim;for(int i=0;i<lim;i++) A[i]=f[i]%P*inv%P;
}else for(int i=0;i<lim;i++) A[i]=f[i]%P;
}
void mul(int *A,int *B,int la,int lb){
int lim=bceil(la+la);cpy(sav,B,la);
NTT(A,lim,1);NTT(sav,lim,1);px(A,sav,lim);NTT(A,lim,-1);
clr(A+lb,lim-lb);clr(sav,lim);
}
void inv_init(int lim){
inv[1]=1;for(int i=2;i<=lim;i++) inv[i]=1ll*inv[P%i]*(P-P/i)%P;
}
int Fac[MAXN],iFac[MAXN];
void Fac_init(int lim){
Fac[0]=iFac[0]=1;
for(int i=1;i<=lim;i++) Fac[i]=1ll*Fac[i-1]*i%P,iFac[i]=1ll*iFac[i-1]*inv[i]%P;
}
void FFP_NTT(int *A,int lim,int type){
cpy(sav,iFac,lim);tpre(lim);
if(type==-1) for(int i=1;i<lim;i+=2) sav[i]=P-sav[i];
mul(A,sav,lim,lim);
}
void FFP_mul(int *A,int *B,int la,int lb){
int lim=bceil(la+la);static int sav[MAXN];
FFP_NTT(A,lim,1);FFP_NTT(B,lim,1);
px(A,B,lim);px(A,Fac,lim);
FFP_NTT(A,lim,-1);clr(A+lb,lim-lb);clr(sav,lim);
}
void print(int *A,int lim){
for(int i=0;i<lim;i++) write(A[i]),putchar(' ');
putchar('\n');
}
int n,m,a[MAXN],b[MAXN];
int main(){
return 0;
}
任意模数
#include<bits/stdc++.h>
#define db long double
#define ll long long
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define bceil(n) (1<<__lg(n-1)+1)
using namespace std;
int read(){
int a=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+(ch^'0'),ch=getchar();
return a;
}
void write(int a){
if(a>9) write(a/10);
putchar(a%10+'0');
}
const int MAXN=2e5+10,P=1e9+7;
ll qpow(ll a,ll b=P-2){
if(a==1) return 1;
ll ans=1;
while(b){if(b&1) ans=ans*a%P;a=a*a%P;b>>=1;}
return ans;
}
const db Pi=acos(-1.0);
struct Complex{
db Re,Im;Complex(db x=0,db y=0){Re=x,Im=y;}
Complex conj(){return Complex(Re,-Im);}
const Complex operator+(const Complex a)const{return Complex(Re+a.Re,Im+a.Im);}
const Complex operator-(const Complex a)const{return Complex(Re-a.Re,Im-a.Im);}
const Complex operator*(const Complex a)const{return Complex(Re*a.Re-Im*a.Im,Re*a.Im+Im*a.Re);}
};
int l,r[MAXN];
void tpre(int lim){
if(l==lim) return;l=lim;
for(int i=0;i<lim;i++) r[i]=(r[i>>1]>>1)|((i&1)?lim>>1:0);
}
void FFT(Complex *A,int lim,int type){
tpre(lim);for(int i=0;i<lim;i++) if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=1;mid<lim;mid<<=1){
Complex Wn(cos(Pi/mid),type*sin(Pi/mid));
for(int R=mid<<1,j=0;j<lim;j+=R){
Complex w(1,0);
for(int k=0;k<mid;k++,w=w*Wn){
Complex x=A[j+k],y=w*A[j+mid+k];
A[j+k]=x+y;A[j+mid+k]=x-y;
}
}
}
}
void mul(int *A,int *B,int lim){
static Complex f[MAXN],g[MAXN],fi[MAXN],gi[MAXN];
for(int i=0;i<lim;i++)
f[i].Re=A[i]>>15,f[i].Im=A[i]&32767,g[i].Re=B[i]>>15,g[i].Im=B[i]&32767;
FFT(f,lim,1);FFT(g,lim,1);
for(int i=1;i<lim;i++) fi[i]=f[lim-i].conj();fi[0]=f[0].conj();
for(int i=1;i<lim;i++) gi[i]=g[lim-i].conj();gi[0]=g[0].conj();
for(int i=0;i<lim;i++){
Complex x=(f[i]+fi[i])*Complex(0.5,0),xi=(f[i]-fi[i])*Complex(0,-0.5),
y=(g[i]+gi[i])*Complex(0.5,0),yi=(g[i]-gi[i])*Complex(0,-0.5);
f[i]=x*y+(x*yi+y*xi)*Complex(0,1),fi[i]=xi*yi;
}FFT(f,lim,-1);FFT(fi,lim,-1);
for(int i=0;i<lim;i++){
int x=(ll)(f[i].Re/lim+0.5)%P,y=(ll)(f[i].Im/lim+0.5)%P,z=(ll)(fi[i].Re/lim+0.5)%P;
A[i]=((1ll*x*(1<<30)+1ll*y*(1<<15)+z)%P+P)%P;
}for(int i=0;i<lim;i++) f[i]=fi[i]=g[i]=gi[i]=Complex(0,0);
}
void invp(int *A,int lim){
int n=bceil(lim);
static int w[MAXN<<1],r[MAXN<<1],sav[MAXN<<1];
w[0]=qpow(A[0]);
for(int ln=2;ln<=n;ln<<=1){
for(int i=0;i<(ln>>1);i++) r[i]=w[i];
cpy(sav,A,ln);mul(r,sav,ln);clr(r,ln>>1);
cpy(sav,w,ln);mul(r,sav,ln);
for(int i=ln>>1;i<ln;i++) w[i]=(w[i]*2ll-r[i]+P)%P;
}cpy(A,w,lim);clr(w,n);clr(r,n);
}
int n,m,a[MAXN],b[MAXN];
int main(){
return 0;
}