多 项 式 全 家 桶
恶心人的多项式。
C风格(较快)
#include
#define clr(f,len) memset(f,0,(len)<<2)
#define cpy(f,g,len) memcpy(f,g,(len)<<2)
#define IMP(lim,anw) for(i=0;i^(lim);++i)anw
typedef unsigned ui;
const ui M=5e5+5,mod=998244353;
ui lim,inv[M],buf[M<<2];
ui *now=buf,*w[23];
inline void swap(ui&a,ui&b){
ui c=a;a=b;b=c;
}
inline ui Add(const ui&a,const ui&b){
return a+b>=mod?a+b-mod:a+b;
}
inline ui Del(const ui&a,const ui&b){
return b>a?a-b+mod:a-b;
}
inline void px(ui*f,ui*g,const ui&len){
for(ui i=0;i^len;++i)f[i]=1ull*f[i]*g[i]%mod;
}
inline void reverse(ui*f,int len){
for(ui i=0;(i<<1|1)>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;
return ans;
}
inline ui Getlen(const ui&n){
ui len=0;
while((1<>1)/n);
for(i=2;i<(1<=1;--j){
w[j]=now;now+=1<>1,d=M;len^0;len>>=1,--d){
W=w[d];
for(k=0;k^n;k+=len<<1){
fl=f+(k);fr=f+(k|len);
IMP(len,(x=fl[i],y=fr[i])),fl[i]=Add(x,y),fr[i]=1ull*Del(x,y)*W[i]%mod;
}
}
}
inline void IDFT(ui*f,const ui&n,const ui&M){
ui i,k,d,x,y,*W,*fl,*fr,len;
for(len=1,d=1;len^n;len<<=1,++d){
W=w[d];
for(k=0;k^n;k+=len<<1){
fl=f+(k);fr=f+(k|len);
IMP(len,(x=fl[i],y=1ull*fr[i]*W[i]%mod)),fl[i]=Add(x,y),fr[i]=Del(x,y);
}
}
k=pow(n);IMP(n,f[i]=1ull*f[i]*k%mod);
for(i=1;(i<<1)
使用 vector 封装(较慢)
#include
#include
#include
#include
#define IMP(lim,anw) for(i=0;i^(lim);++i)anw
typedef unsigned ui;
const ui M=5e6+5,mod=998244353;
ui lim,Inv[M],buf[M<<2];ui*now=buf,*w[23];
inline void swap(ui&a,ui&b){
ui c=a;a=b;b=c;
}
inline ui Add(const ui&a,const ui&b){
return a+b>=mod?a+b-mod:a+b;
}
inline ui Del(const ui&a,const ui&b){
return b>a?a-b+mod:a-b;
}
inline ui max(const ui&a,const ui&b){
return a>b?a:b;
}
inline void write(ui n){
static char s[10];ui top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top--]),top);
}
inline ui read(){
ui n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline ui pow(ui a,ui b=mod-2){
ui ans=1;
for(;b;b>>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;
return ans;
}
inline ui Getlen(const ui&n){
ui len=0;
while((1<>1)/n);
for(i=2;i<(1<=1;--j){
w[j]=now;now+=1<F;
Poly(const Poly&G){F=G.F;}
Poly(const std::vectorG){F=G;}
Poly(const ui&x=0){if(x)F=std::vector(x);}
inline Poly&resize(const ui&len){
F.resize(len);return*this;
}
inline ui size()const{
return F.size();
}
inline ui&operator[](const ui&id){
return F[id];
}
inline void push_back(const ui&x){
F.push_back(x);
}
inline Poly&reverse(){
std::reverse(F.begin(),F.end());return*this;
}
inline Poly operator>>(const ui&x){
ui i;Poly G;IMP(F.size()-x,G.push_back(F[i+x]));return G;
}
inline Poly operator<<(const ui&x){
ui i;Poly G;G.resize(x);IMP(F.size(),G.push_back(F[i]));return G;
}
inline void px(Poly G){
F.resize(max(F.size(),G.size()));G.resize(F.size());
for(ui i(0);i^F.size();++i)F[i]=1ull*F[i]*G[i]%mod;
}
inline Poly&Der(){
for(ui i(1);i^F.size();++i)F[i-1]=1ull*F[i]*i%mod;F.pop_back();
return*this;
}
inline Poly&Int(){
F.push_back(0);
for(ui i(F.size()-1);i;--i)F[i]=1ull*F[i-1]*::Inv[i]%mod;F[0]=0;
return*this;
}
inline void DFT(const ui&M){
ui i,k,d,x,y,len,*W;F.resize(1<>1,d=M;len;len>>=1,--d){
W=w[d];
for(k=0;k^F.size();k+=len<<1){
IMP(len,(x=F[i|k],y=F[i|k|len])),F[i|k]=Add(x,y),F[i|k|len]=1ull*Del(x,y)*W[i]%mod;
}
}
}
inline void IDFT(const ui&M){
ui i,k,d,x,y,len,*W;F.resize(1<F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
IMP(F.size(),F[i]=Add(F[i],G[i]));return F;
}
inline Poly operator-(Poly G)const{
Poly F=this->F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
IMP(F.size(),F[i]=Del(F[i],G[i]));return F;
}
inline Poly operator*(const ui&x)const{
Poly F=this->F;ui i;
IMP(F.size(),F[i]=1ull*F[i]*x%mod);return F;
}
inline Poly operator*(Poly G)const{
Poly F=*this;const ui&len=F.size()+G.size()-1,M=Getlen(len);
G.resize(1<>=(const ui&x){
return*this=operator>>(x);
}
inline Poly&operator<<=(const ui&x){
return*this=operator<<(x);
}
inline Poly&operator+=(const Poly&G){
return*this=*this+G;
}
inline Poly&operator-=(const Poly&G){
return*this=*this-G;
}
inline Poly&operator*=(const Poly&G){
return*this=*this*G;
}
inline Poly&operator/=(const Poly&G){
return*this=*this/G;
}
inline Poly&operator%=(const Poly&G){
return*this=*this%G;
}
inline Poly&inv(){
Poly b1,b2,b3;if(!F.empty())b1.push_back(::pow(F[0]));
ui i,M=Getlen(F.size()),len;
for(len=1;len<=M;++len){
b3=b1*2;(b2=F).resize(1<Der()*=G.inv()).resize(len)).Int();
}
inline Poly&exp(){
Poly b1,b2;ui i,M=Getlen(F.size()),len;b1.push_back(1);
for(len=1;len<=M;++len){
b2=b1;b2.resize(1<ln();IMP(F.size(),F[i]=1ull*F[i]*k%mod);return this->exp();
}
};
inline Poly resize(Poly F,const ui&n){
return F.resize(n);
}
inline Poly reverse(Poly F){
return F.reverse();
}
inline Poly Int(Poly F){
return F.Int();
}
inline Poly Der(Poly F){
return F.Der();
}
inline Poly px(Poly F,Poly G){
return F.px(G),F;
}
inline Poly inv(Poly F){
return F.inv();
}
inline Poly ln(Poly F){
return F.ln();
}
inline Poly exp(Poly F){
return F.exp();
}
inline Poly sqrt(Poly F){
return F.sqrt();
}
inline Poly pow(Poly F,const ui&k){
return F.pow(k);
}