目前包含:多项式乘法+多项式求逆+多项式求ln+多项式求exp+多项式快速幂+多项式开根(求二次剩余的sqrt)…(跑得好慢啊QAQ)
#pragma GCC optimize(3,"Ofast","inline")
#include
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int mod=998244353,inv2=(mod+1)>>1,mrt=31596;
namespace {
inline int Add(const int &x,const int &y) {
int res=x+y;
if(res>=mod)
res-=mod;
return res;
}
inline int Sub(const int &x,const int &y) {
int res=x-y;
if(res<0)
res+=mod;
return res;
}
inline int Mul(const int &x,const int &y) {
return 1ll*x*y%mod;
}
inline int Pow(int x,int y=mod-2) {
int res=1;
while(y) {
if(y&1)
res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
}
const int fmaxn=19,Fmaxn=(1<<fmaxn)+5,G=3;
int nxtl[Fmaxn],nxtlim[Fmaxn],inv[Fmaxn];
namespace Solve {
map<int,int>ins;
inline int Solve2(int p) {
static int j,res;
if(p==0)
return 0;
j=1;
for(int i=0;i<mrt;++i)
ins[j]=i,j=Mul(j,G);
res=0,j=Pow(j);
for(int i=0;i<=mrt;++i) {
if(ins.count(p)) {
res=(res+ins[p])%(mod-1);
if(res&1)
return -1;
res=Pow(G,res/2);
if(mod-res<res)
res=mod-res;
return res;
}
p=Mul(p,j),res=(res+mrt)%(mod-1);
}
return -1;
}
}
namespace Poly {
static int root[fmaxn][Fmaxn],mx,rev[Fmaxn];
inline void Rev(int l) {
rev[0]=0;
for(int i=1;i<(1<<l);++i)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
inline void DFT(vector<int>&a,int bit) {
if(mx<bit) {
for(int i=mx;i<bit;++i) {
int len=1<<i,w0=Pow(G,(mod-1)/(len<<1)),w=1;
for(int j=0;j<len;++j)
root[i][j]=w,w=Mul(w,w0);
}
mx=bit;
}
for(int i=1;i<1<<bit;++i)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int i=0,len=1;i<bit;++i,len<<=1)
for(int j=0;j<(1<<bit);j+=(len<<1))
for(int k=0;k<len;++k) {
int x=a[j+k],y=Mul(a[j+k+len],root[i][k]);
a[j+k]=Add(x,y),a[j+k+len]=Sub(x,y);
}
}
inline void IDFT(vector<int>&a,int bit) {
int len=(1<<bit),inv=Pow(len);
reverse(a.begin()+1,a.end());
DFT(a,bit);
for(int i=0;i<len;++i)
a[i]=Mul(a[i],inv);
}
inline void FFT(vector<int>a,vector<int>b,vector<int>&c) {
c.clear();
int la=a.size(),lb=b.size(),lc=la+lb-1,l=nxtl[lc],lim=nxtlim[lc];
a.resize(lim),b.resize(lim),c.resize(lim);
Rev(l),DFT(a,l),DFT(b,l);
for(int i=0;i<lim;++i)
c[i]=Mul(a[i],b[i]);
IDFT(c,l);
c.resize(lc);
}
inline void AddPoly(vector<int>a,vector<int>b,vector<int>&c) {
c.clear();
int la=a.size(),lb=b.size(),lc=max(la,lb);
c.resize(lc);
for(int i=0;i<lc;++i) {
if(i<la)
c[i]=Add(c[i],a[i]);
if(i<lb)
c[i]=Add(c[i],b[i]);
}
}
inline void SubPoly(vector<int>a,vector<int>b,vector<int>&c) {
c.clear();
int la=a.size(),lb=b.size(),lc=max(la,lb);
c.resize(lc);
for(int i=0;i<lc;++i) {
if(i<la)
c[i]=Add(c[i],a[i]);
if(i<lb)
c[i]=Sub(c[i],b[i]);
}
}
inline void Inv(vector<int>f,vector<int>&g,int len) {
g.clear();
int lim=nxtlim[len];
f.resize(lim),g.resize(lim);
g[0]=Pow(f[0]);
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i<<1),l(i<<1),o(i<<1);
for(int j=0;j<i;++j)
h[j]=f[j];
for(int j=0;j<i>>1;++j)
l[j]=g[j];
Rev(p+1),DFT(h,p+1),DFT(l,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(h[j],Mul(l[j],l[j]));
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=Sub(Mul(2,g[j]),o[j]);
}
g.resize(len);
}
inline void Ln(vector<int>f,vector<int>&g,int len) {
g.clear();
vector<int>h(len,0);
for(int i=1;i<len;++i)
h[i-1]=Mul(f[i],i);
h[len-1]=0;
Inv(f,g,len);
FFT(g,h,g);
for(int i=len-1;i;--i)
g[i]=Mul(g[i-1],::inv[i]);
g[0]=0;
g.resize(len);
}
inline void Exp(vector<int>f,vector<int>&g,int len,int init) {
int lim=nxtlim[len];
if(init)
g.clear(),g.push_back(1);
f.resize(lim),g.resize(lim);
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i<<1),l,o(i<<1,0);
for(int j=0;j<i>>1;++j)
h[j]=g[j];
Ln(h,l,i);
for(int j=0;j<i;++j)
l[j]=Sub(f[j]+(!j),l[j]),l.push_back(0);
Rev(p+1),DFT(h,p+1),DFT(l,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(h[j],l[j]);
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=o[j];
}
g.resize(len);
}
inline void Pow(vector<int>f,vector<int>&g,int len,ll k) {
g.clear();
vector<int>h;
Ln(f,h,len);
int o=k%mod;
for(int i=0;i<len;++i)
h[i]=Mul(h[i],o);
g.push_back(::Pow(f[0],(int)(k%(mod-1))));
Exp(h,g,len,0);
}
inline void Sqrt(vector<int>f,vector<int>&g,int len) {
g.clear();
g.push_back(Solve::Solve2(f[0]));
int lim=nxtlim[len];
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i),l,o(i<<1,0);
g.resize(i<<1);
for(int j=0;j<i;++j)
h[j]=g[j];
Inv(h,l,i);
l.resize(i<<1);
for(int j=0;j<min(i,(int)f.size());++j)
o[j]=f[j];
Rev(p+1),DFT(g,p+1),DFT(l,p+1),DFT(o,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(Add(g[j],Mul(l[j],o[j])),inv2);
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=o[j];
g.resize(i);
}
g.resize(len);
}
}
Luogu4720模板,顺便修改了下上面的板子,将空间压回了O(n)
// luogu-judger-enable-o2
#pragma GCC optimize(3,"Ofast","inline")
#include
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int mod=998244353,G=3,fmaxn=18,Fmaxn=1<<18;
inline int Add(int x,int y) {
return (x+=y)>=mod?x-mod:x;
}
inline int Sub(int x,int y) {
return (x-=y)<0?x+mod:x;
}
inline int Mul(int x,int y) {
return 1ll*x*y%mod;
}
inline int Pow(int x,int y=mod-2) {
int res=1;
for(;y;x=Mul(x,x),y>>=1)
if(y&1)
res=Mul(res,x);
return res;
}
namespace Poly {
static int root[Fmaxn<<1],beg[fmaxn],nxtl[Fmaxn],nxtlim[Fmaxn],rev[Fmaxn],cnt,mx;
inline void Init() {
nxtl[1]=0,nxtlim[1]=1;
for(int i=1;i<Fmaxn-1;++i)
nxtl[i+1]=nxtl[i]+(i==(i&-i)),nxtlim[i+1]=nxtlim[i]<<(i==(i&-i));
}
inline void Rev(int bit) {
rev[0]=0;
for(int i=1;i<1<<bit;++i)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
}
inline void DFT(vector<int>&a,int bit) {
for(;mx<=bit;++mx) {
int len=1<<mx,w0=Pow(G,(mod-1)/(len<<1)),w=1;
beg[mx]=cnt;
for(int i=0;i<len;++i,w=Mul(w,w0))
root[cnt++]=w;
}
for(int i=1;i<1<<bit;++i)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int i=0,len=1;i<bit;++i,len<<=1)
for(int j=0;j<1<<bit;j+=(len<<1))
for(int k=0;k<len;++k) {
int x=a[j+k],y=Mul(a[len+j+k],root[beg[i]+k]);
a[j+k]=Add(x,y),a[len+j+k]=Sub(x,y);
}
}
inline void IDFT(vector<int>&a,int bit) {
int len=1<<bit,inv=Pow(len);
reverse(a.begin()+1,a.end()),DFT(a,bit);
for(int i=0;i<len;++i)
a[i]=Mul(a[i],inv);
}
inline void FFT(vector<int>a,vector<int>b,vector<int>&c) {
int la=a.size(),lb=b.size(),lc=la+lb-1,l=nxtl[lc],lim=nxtlim[lc];
a.resize(lim),b.resize(lim),c.resize(lim),Rev(l),DFT(a,l),DFT(b,l);
for(int i=0;i<lim;++i)
c[i]=Mul(a[i],b[i]);
IDFT(c,l),c.resize(lc);
}
}
vector<int>F,H,A,B;
int n;
inline void Div(int l,int r) {
if(l==r)
return;
int mid=(l+r)>>1;
Div(l,mid);
A.clear(),B.clear();
for(int i=l;i<=mid;++i)
A.push_back(F[i]);
for(int i=1;i<=r-l;++i)
B.push_back(H[i]);
Poly::FFT(A,B,A);
for(int i=mid+1;i<=r;++i)
F[i]=Add(F[i],A[i-l-1]);
Div(mid+1,r);
}
int main() {
Poly::Init(),read(n),F.resize(n),F[0]=1,H.resize(n);
for(int i=1;i<n;++i)
read(H[i]);
Div(0,n-1);
for(int i=0;i<n;++i)
printf("%d ",F[i]);
puts("");
}
只是加个板子QAQ…(注意每次使用前都要Clear一下!!!)
const int maxn=500005;
namespace SAM {
struct Node {
int fa,len,ch[26];
inline void Clear() {
fa=len=0,memset(ch,0,sizeof ch);
}
}T[maxn<<1];
int lst,cnt,sz[maxn<<1],tot[maxn<<1],sa[maxn<<1];
inline void Clear() {
T[lst=cnt=1].Clear();
}
inline int NewNode() {
T[++cnt].Clear();
return cnt;
}
inline void Insert(int c) {
int p=lst,np=NewNode();
lst=np,T[np].len=T[p].len+1;
for(;p&&!T[p].ch[c];p=T[p].fa)
T[p].ch[c]=np;
if(!p)
T[np].fa=1;
else {
int q=T[p].ch[c];
if(T[q].len==T[p].len+1)
T[np].fa=q;
else {
int nq=NewNode();
T[nq]=T[q],T[nq].len=T[p].len+1,T[np].fa=T[q].fa=nq;
for(;p&&T[p].ch[c]==q;p=T[p].fa)
T[p].ch[c]=nq;
}
}
sz[np]=1;
}
inline void Build() {
for(int i=1;i<=cnt;++i)
tot[T[i].len]++;
for(int i=1;i<=n;++i)
tot[i]+=tot[i-1];
for(int i=cnt;i;--i)
sa[tot[T[i].len]--]=i;
}
}
inline void FMT(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;++j)
if(j&i)
x[j]=Add(x[j],x[j^i]);
}
inline void IFMT(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;++j)
if(j&i)
x[j]=Sub(x[j],x[j^i]);
}
inline void FWTor(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k)
x[j+k+i]=Add(x[j+k],x[j+k+i]);
}
inline void IFWTor(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k)
x[j+k+i]=Sub(x[j+k],x[j+k+i]);
}
inline void FWTand(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k)
x[j+k]=Add(x[j+k],x[j+k+i]);
}
inline void IFWTand(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k)
x[j+k]=Sub(x[j+k],x[j+k+i]);
}
inline void FWTxor(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k) {
int y=x[j+k],z=x[j+k+i];
x[j+k]=Add(y,z),x[j+k+i]=Sub(y,z);
}
}
inline void IFWTxor(vector<int>&x) {
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=(i<<1))
for(int k=0;k<i;++k) {
int y=x[j+k],z=x[j+k+i];
x[j+k]=Half(Add(y,z)),x[j+k+i]=Half(Sub(y,z));
}
}
戳这里
#pragma GCC optimize(3,"Ofast","inline")
#include
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=400005;
int vi[maxn];
namespace LCT {
struct Node {
int ch[2],tag,fa,val;
inline void Clear() {
ch[0]=ch[1]=tag=fa=val=0;
}
inline int& operator [] (int x) {
return this->ch[x];
}
}T[maxn];
inline int Val(int x) {
return x?T[x].val:0;
}
inline void Reverse(int x) {
if(x)
swap(T[x][0],T[x][1]),T[x].tag^=1;
}
inline void Pushup(int x) {
T[x].val=Val(T[x][0])^vi[x]^Val(T[x][1]);
}
inline void Pushdown(int x) {
if(T[x].tag)
Reverse(T[x][0]),Reverse(T[x][1]),T[x].tag=0;
}
inline int Isroot(int x) {
return T[T[x].fa][0]!=x&&T[T[x].fa][1]!=x;
}
inline int Isright(int x) {
return T[T[x].fa][1]==x;
}
inline void Pushtag(int x) {
if(!Isroot(x))
Pushtag(T[x].fa);
Pushdown(x);
}
inline void Rotate(int x) {
int y=T[x].fa,z=T[y].fa,r=Isright(x),l=r^1;
if(!Isroot(y))
T[z][Isright(y)]=x;
T[x].fa=z,T[y].fa=x,T[T[x][l]].fa=y,T[y][r]=T[x][l],T[x][l]=y,Pushup(y),Pushup(x);
}
inline void Splay(int x) {
Pushtag(x);
for(int y;!Isroot(x);Rotate(x))
if(!Isroot(y=T[x].fa))
Rotate(Isright(y)^Isright(x)?x:y);
}
inline void Access(int x) {
for(int y=0;x;y=x,x=T[x].fa)
Splay(x),T[x][1]=y,Pushup(x);
}
inline void Makeroot(int x) {
Access(x),Splay(x),Reverse(x);
}
inline int Findroot(int x) {
Access(x),Splay(x);
for(;T[x][0];x=T[x][0]);
return Splay(x),x;
}
inline void Findpath(int x,int y) {
Makeroot(x),Access(y),Splay(y);
}
inline void Link(int x,int y) {
Makeroot(x);
if(Findroot(y)==x)
return;
T[x].fa=y;
}
inline void Cut(int x,int y) {
Makeroot(x);
if(Findroot(y)!=x)
return;
Splay(y);
if(T[y][0]!=x)
return;
T[x].fa=T[y][0]=0,Pushup(y);
}
}
using LCT::T;
int n,m;
int main() {
read(n),read(m);
for(int i=1;i<=n;++i)
read(vi[i]),T[i].val=vi[i];
for(int ty,u,v;m--;) {
read(ty),read(u),read(v);
if(ty==0)
LCT::Findpath(u,v),printf("%d\n",T[v].val);
if(ty==1)
LCT::Link(u,v);
if(ty==2)
LCT::Cut(u,v);
if(ty==3)
LCT::Access(u),LCT::Splay(u),vi[u]=T[u].val=v,LCT::Pushup(u);
}
}