- 从 \(\texttt{{\color{black}S}{\color{red}intilla}}\) 老师那里蒯来的,改了马蜂。
const int P=998244353,Pi=499122177;
inline int inc(int a,int b){return(a+=b)>=P?a-P:a;}
inline int dec(int a,int b){return(a-=b)<0?a+P:a;}
inline int mul(int a,int b){int s=1ll*a*b%P;return s<0?s+P:s;}
inline void add(int &a,int b){(a+=b)>=P?a-=P:1;}
inline void sub(int &a,int b){(a-=b)<0?a+=P:1;}
inline int sgn(int x){return x&1?P-1:1;}
inline int qpow(int a,int b){int res=1;while(b){if(b&1)res=mul(res,a);a=mul(a,a);b>>=1;}return res;}
namespace Poly{
const int ng=3;
const int ngi=(P+1)/3;
const int L=20;
const int N=1<<L;
int w[N],pinv[N];
inline void init_w(){
w[0]=pinv[1]=1;
for(int i=0;i<L;i++)
w[1<<i]=qpow(ng,(P-1)>>(i+2));
for(int i=2;i<N;i++){
w[i]=mul(w[i&-i],w[i&i-1]);
pinv[i]=P-mul(P/i,pinv[P%i]);
}
}
inline void dif(int *f,int n){
int t,k,*tw,*tf,*pf;
for(k=n>>1;k;k>>=1){
for(tw=w,tf=f;tf!=f+n;tw++,tf+=k<<1){
for(pf=tf;pf!=tf+k;pf++){
t=mul(pf[k],*tw);
pf[k]=dec(*pf,t);
add(*pf,t);
}
}
}
}
inline void dit(int *f,int n){
int t,k,*tw,*tf,*pf;
for(k=1;k<n;k<<=1){
for(tw=w,tf=f;tf!=f+n;tw++,tf+=k<<1){
for(pf=tf;pf!=tf+k;pf++){
t=pf[k];
pf[k]=mul(dec(*pf,t),*tw);
add(*pf,t);
}
}
}
int iv=P-(P-1)/n;
for(int i=0;i<n;i++)
f[i]=mul(f[i],iv);
reverse(f+1,f+n);
}
int f0[N];
struct poly{
vector<int>a;
inline int size(){return(int)a.size();}
inline int& operator[](int i){return a[i];}
inline void clear(){a.clear();}
inline void resize(int n){a.resize(n);}
inline poly(int n=0,int x=0){a.resize(n,x);}
inline poly(const vector<int>&o){a=o;}
inline poly(const poly &o){a=o.a;}
inline void print(){
int n=size();poly a=*this;
for(int i=0;i<n;i++)write(a[i]),putchar(' ');puts("");
}
inline void operator+=(poly b){
int n=size(),m=b.size();
resize(max(n,m));
for(int i=0;i<m;i++)
add(a[i],b[i]);
}
inline friend poly operator+(poly a,poly b){
a+=b;
return a;
}
inline void operator-=(poly b){
int n=size(),m=b.size();
resize(max(n,m));
for(int i=0;i<m;i++)
sub(a[i],b[i]);
}
inline friend poly operator-(poly a,poly b){
a-=b;
return a;
}
inline void operator<<=(int k){
int n=size();
resize(n+k);
for(int i=0;i<n;i++)
a[i+k]=a[i];
for(int i=0;i<k;i++)
a[i]=0;
}
inline friend poly operator<<(poly a,int k){
a<<=k;
return a;
}
inline void operator*=(int b){
int n=size();
for(int i=0;i<n;i++)
a[i]=mul(a[i],b);
}
inline friend poly operator*(poly a,int b){
a*=b;
return a;
}
inline void operator /=(int b){
int n=size(),iv=qpow(b,P-2);
for(int i=0;i<n;i++)
a[i]=mul(a[i],iv);
}
inline friend poly operator/(poly a,int b){
a/=b;
return a;
}
inline void operator>>=(int k){
int n=size();
if(n<=k){
*this=poly();
return;
}
for(int i=k;i<n;i++)
a[i-k]=a[i];
resize(n-k);
}
inline friend poly operator>>(poly a,int k){
a>>=k;
return a;
}
inline poly diff(){
int n=size();
if(!n)
return poly();
poly res(n-1);
for(int i=1;i<n;i++)
res[i-1]=mul(a[i],i);
return res;
}
inline poly intg(){
int n=size();
poly res(n+1);
for(int i=0;i<n;i++)
res[i+1]=mul(a[i],pinv[i+1]);
return res;
}
inline void dft(){
int n=size();
assert(n==(n&-n));
for(int i=0;i<n;i++)
f0[i]=a[i];
dif(f0,n);
for(int i=0;i<n;i++)
a[i]=f0[i];
}
inline void idft(){
int n=size();
assert(n==(n&-n));
for(int i=0;i<n;i++)
f0[i]=a[i];
dit(f0,n);
for(int i=0;i<n;i++)
a[i]=f0[i];
}
inline void operator*=(poly b){
int n=size(),m=b.size();
int lim=1;
while(lim<n+m-1)
lim<<=1;
resize(lim),dft();
b.resize(lim),b.dft();
for(int i=0;i<lim;i++)
a[i]=mul(a[i],b[i]);
idft(),resize(n+m-1);
}
inline friend poly operator*(poly a,poly b){
a*=b;
return a;
}
inline void operator/=(poly b){
int n=size(),m=b.size();
assert(n>=m);
reverse(a.begin(),a.end());
reverse(b.a.begin(),b.a.end());
resize(n-m+1),b.resize(n-m+1);
*this*=b.inv(),resize(n-m+1);
reverse(a.begin(),a.end());
}
inline friend poly operator/(poly a,poly b){
a/=b;
return a;
}
inline void operator%=(poly b){
int m=b.size();
poly q=*this/b;
*this-=q*b,resize(m-1);
}
inline friend poly operator%(poly a,poly b){
a%=b;
return a;
}
inline poly inv(){
int n=size();
assert(n);
assert(a[0]);
poly res(1),cp;
res[0]=qpow(a[0],P-2);
for(int o=2;o<(n<<1);o<<=1){
cp=a;cp.resize(o);cp.resize(o<<1);
res.resize(o<<1);
res.dft(),cp.dft();
for(int i=0;i<o<<1;i++)
res[i]=mul(res[i],dec(2,mul(res[i],cp[i])));
res.idft(),res.resize(o);
}
res.resize(n);
return res;
}
inline poly ln(){
int n=size();
assert(n);
assert(a[0]==1);
poly res=(diff()*inv()).intg();
res.resize(n);
return res;
}
inline poly exp(){
int n=size();
assert(n);
assert(!a[0]);
poly res(1),fln,cp;
res[0]=1;
for(int o=2;o<(n<<1);o<<=1){
cp=a;cp.resize(o);cp.resize(o<<1);
res.resize(o);fln=res.ln();fln.resize(o<<1);
res.resize(o<<1);
res.dft(),fln.dft(),cp.dft();
for(int i=0;i<o<<1;i++)
res[i]=mul(res[i],dec(1,dec(fln[i],cp[i])));
res.idft(),res.resize(o);
}
res.resize(n);
return res;
}
inline poly pow(int k){
poly cp=*this;
assert(cp.size());
assert(cp.a[0]);
int c=cp.a[0];
cp/=c;
cp=(cp.ln()*k).exp();
cp*=qpow(c,k);
return cp;
}
inline poly sqrt(){
int n=size();
assert(n);
assert(a[0]==1);
poly res(1),fiv,cp;
res[0]=a[0];
for(int o=2;o<(n<<1);o<<=1){
cp=a;cp.resize(o);cp.resize(o<<1);
res.resize(o);fiv=res.inv();fiv.resize(o<<1);
res.resize(o<<1);
res.dft(),fiv.dft(),cp.dft();
for(int i=0;i<o<<1;i++)
res[i]=mul(inc(mul(res[i],res[i]),cp[i]),mul((P+1)/2,fiv[i]));
res.idft(),res.resize(o);
}
res.resize(n);
return res;
}
inline poly fwt_or(poly a,int op){
int m=a.size();
for(int o=2,k=1;k<m;k<<=1,o<<=1)
for(int i=0;i<m;i+=o)
for(int j=0;j<k;j++)
op?add(a[i|j|k],a[i|j]):sub(a[i|j|k],a[i|j]);
return a;
}
inline poly OR(poly a,poly b){
int m=a.size();
a=fwt_or(a,1);b=fwt_or(b,1);
for(int i=0;i<m;i++)
a[i]=mul(a[i],b[i]);
a=fwt_or(a,0);
return a;
}
inline void operator|=(poly b){
poly q=*this;
*this=OR(*this,b);
}
inline friend poly operator|(poly a,poly b){
a|=b;
return a;
}
inline poly fwt_and(poly a,int op){
int m=a.size();
for(int o=2,k=1;k<m;k<<=1,o<<=1)
for(int i=0;i<m;i+=o)
for(int j=0;j<k;j++)
op?add(a[i|j],a[i|j|k]):sub(a[i|j],a[i|j|k]);
return a;
}
inline poly AND(poly a,poly b){
int m=a.size();
a=fwt_and(a,1);b=fwt_and(b,1);
for(int i=0;i<m;i++)
a[i]=mul(a[i],b[i]);
a=fwt_and(a,0);
return a;
}
inline void operator&=(poly b){
poly q=*this;
*this=AND(*this,b);
}
inline friend poly operator&(poly a,poly b){
a&=b;
return a;
}
inline poly fwt_xor(poly a,int op){
int m=a.size();
for(int o=2,k=1;k<m;k<<=1,o<<=1)
for(int i=0;i<m;i+=o)
for(int j=0;j<k;j++)
if(op){
a[i|j]=inc(a[i|j],a[i|j|k]);
a[i|j|k]=inc(a[i|j],mul(dec(P,a[i|j|k]),2));
}else{
a[i|j]=mul(inc(a[i|j],a[i|j|k]),Pi);
a[i|j|k]=dec(a[i|j],a[i|j|k]);
}
return a;
}
inline poly XOR(poly a,poly b){
int m=a.size();
a=fwt_xor(a,1);b=fwt_xor(b,1);
for(int i=0;i<m;i++)
a[i]=mul(a[i],b[i]);
a=fwt_xor(a,0);
return a;
}
inline void operator^=(poly b){
poly q=*this;
*this=XOR(*this,b);
}
inline friend poly operator^(poly a,poly b){
a^=b;
return a;
}
};
}
using Poly::init_w;
using Poly::poly;
标签:return,全家福,int,poly,inline,size,const
From: https://www.cnblogs.com/QcpyWcpyQ/p/18017037