自己手摸的一套多项式板子,似乎常数并不是很优秀,优化中
默认模数P为998244353
namespace Poly{
void FWT_or(int *a,int len,int Ty){
for(int w=1;w<len;w<<=1)
for(int j=0;j<len;j+=w*2)
rep(i,0,w-1)a[i+j+w]+=a[i+j]*Ty;
}
void FWT_and(int *a,int len,int Ty){
for(int w=1;w<len;w<<=1)
for(int j=0;j<len;j+=w*2)
rep(i,0,w-1)a[i+j]+=a[i+j+w]*Ty;
}
void FWT_xor(int *a,int len,int Ty){
for(int w=1;w<len;w<<=1)
for(int j=0;j<len;j+=w*2)
rep(i,0,w-1){
int t=a[i+j+w];
a[i+j+w]=a[i+j]-t;
a[i+j]+=t;
}
if(Ty==-1)rep(i,0,len-1)a[i]/=len;
}
const double pi=acos(-1);
struct Com{
double x,y;
Com operator +(Com &_)const{
return (Com){x+_.x,y+_.y};
}
Com operator -(Com &_)const{
return (Com){x-_.x,y-_.y};
}
Com operator *(Com &_)const{
return (Com){x*_.x-y*_.y,x*_.y+_.x*y};
}
};
const int M=4e5+10;
int rev[M];
void FFT(Com *a,int len,int Ty){
rep(i,0,len-1)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int w=1;w<len;w<<=1){
Com h={cos(pi/w),sin(pi/w)};
for(int j=0;j<len;j+=w*2){
Com g={1,0};
rep(i,0,w-1){
Com t=a[i+j+w]*g;
a[i+j+w]=a[i+j]-t;
a[i+j]=a[i+j]+t;
g=g*h;
}
}
}
if(!Ty){
reverse(a+1,a+len);
rep(i,0,len-1)a[i].x/=len;
}
}
void NTT(int *a,int len,int Ty){
rep(i,0,len-1)if(i<rev[i])swap(a[i],a[rev[i]]);
for(int w=1;w<len;w<<=1){
int h=Pow(3,(P-1)/w/2);
for(int j=0;j<len;j+=w*2){
int g=1;
rep(i,0,w-1){
int t=1ll*a[i+j+w]*g%P;
a[i+j+w]=a[i+j]-t;
Mod(a[i+j+w]);
a[i+j]=a[i+j]+t;
Mod(a[i+j]);
g=1ll*g*h%P;
}
}
}
if(Ty==-1){
reverse(a+1,a+len);
int inv=Pow(len,P-2);
rep(i,0,len-1)a[i]=1ll*a[i]*inv%P;
}
}
int I[M],T[M],D[M],E[M],L[M],S[M];
void WorkForInv(int *a,int *b,int la){
if(la==1)return b[0]=Pow(a[0],P-2),void();
WorkForInv(a,b,(la+1)>>1);
int len=1;
while(len<=la+la)len<<=1;
rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
rep(i,0,la-1)T[i]=a[i];
NTT(T,len,1),NTT(b,len,1);
rep(i,0,len-1)b[i]=(2ll*b[i]-1ll*b[i]*b[i]%P*T[i]%P+P)%P;
NTT(b,len,-1);
rep(i,0,len-1)T[i]=0;
rep(i,la,len-1)b[i]=0;
}
void inv(int *a,int la){WorkForInv(a,I,la);}
void GetDer(int *a,int *b,int la){
rep(i,1,la-1)b[i-1]=1ll*a[i]*i%P;
b[la-1]=0;
}
void GetInt(int *a,int *b,int la){
drep(i,la-2,0)b[i+1]=1ll*a[i]*Pow(i+1,P-2)%P;
b[0]=0;
}
void ln(int *a,int la){
inv(a,la),GetDer(a,D,la);
int len=1;
while(len<=la+la)len<<=1;
rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
NTT(D,len,1),NTT(I,len,1);
rep(i,0,len-1)T[i]=1ll*D[i]*I[i]%P;
NTT(T,len,-1),GetInt(T,L,len);
rep(i,0,len-1)T[i]=I[i]=D[i]=0;
rep(i,la,len)L[i]=0;
}
void WorkForExp(int *a,int *b,int la){
if(la==1)return b[0]=1,void();
WorkForExp(a,b,(la+1)>>1);
int len=1;
while(len<=la+la)len<<=1;
rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
ln(b,la),GetDer(b,D,la);
rep(i,0,la-1)T[i]=a[i];
NTT(T,len,1),NTT(b,len,1),NTT(L,len,1);
rep(i,0,len-1)b[i]=1ll*b[i]*(P+1-L[i]+T[i])%P;
NTT(b,len,-1);
rep(i,0,len-1)T[i]=L[i]=D[i]=0;
rep(i,la,len-1)b[i]=0;
}
void exp(int *a,int la){WorkForExp(a,E,la);}
int inv2=Pow(2,P-2);
void WorkForSqrt(int *a,int *b,int la){
if(la==1)return b[0]=1,void();
WorkForSqrt(a,b,(la+1)>>1);
int len=1;
while(len<=la+la)len<<=1;
rep(i,0,len-1)rev[i]=rev[i>>1]>>1|((i&1)*len/2);
inv(b,la);
rep(i,0,la-1)T[i]=a[i];
NTT(I,len,1),NTT(T,len,1);
rep(i,0,len-1)T[i]=1ll*T[i]*I[i]%P;
NTT(T,len,-1);
rep(i,0,la-1)b[i]=1ll*(b[i]+T[i])*inv2%P;
rep(i,0,len-1)T[i]=I[i]=0;
}
void sqrt(int *a,int la){WorkForSqrt(a,S,la);}
}
恶心坏我了,呕~~~