板子小记

5 篇文章 0 订阅
5 篇文章 0 订阅

多项式

  目前包含:多项式乘法+多项式求逆+多项式求ln+多项式求exp+多项式快速幂+多项式开根(求二次剩余的sqrt)…(跑得好慢啊QAQ)

Code

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
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);
    }
}

分治FFT

  Luogu4720模板,顺便修改了下上面的板子,将空间压回了O(n)

Code

// luogu-judger-enable-o2
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
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("");
}

SAM

  只是加个板子QAQ…(注意每次使用前都要Clear一下!!!)

Code

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;
	}
}

FMT

Code

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]);
}

FWT

Code

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));
			}
}

无旋Treap

  戳这里

LCT

Code[LuoguP3690]

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
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);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值