KMP
int KMP(char S[200010],char T[200010],int wz[200010],int n,int m)
{
ne[0]=-1;
for(int i=1;i<=m;i++)
{
int t=ne[i-1];
while(t!=-1&&T[i-1]!=T[t])
t=ne[t];
ne[i]=t+1;
}
int a=0,b=0,sl=0;
while(a<=n)
{
if(b==m)
{
wz[sl++]=a-m;
b=ne[b];
}
if(b==-1||S[a]==T[b])
a+=1,b+=1;
else
b=ne[b];
}
return sl;
}
点双连通分量
void tarjan(int u,int f)
{
st[tp++]=u;
dfn[u]=low[u]=++tm;
for(int i=fr[u];i!=-1;i=ne[i])
{
if(v[i]==f)continue;
if(!dfn[v[i]])
{
int la=tp,lb=tb;
sb[tb++]=i;tarjan(v[i],u);
if(low[v[i]]>=dfn[u])
{
ss+=1;
for(int j=la;j<tp;j++)
bc[ss].push_back(st[j]);
for(int j=lb;j<tb;j++)
bb[ss].push_back(sb[j]);
tp=la;tb=lb;bc[ss].push_back(u);
}
low[u]=min(low[u],low[v[i]]);
}
else
{
low[u]=min(low[u],dfn[v[i]]);
sb[tb++]=i;
}
}
}
行列式
int hangls(int sz[102][102],int n)
{
int jg=1;
for(int i=0;i<n;i++)
{
int wz=-1;
for(int j=i;j<n;j++)
{
if(sz[j][i]!=0)
{
wz=j;
break;
}
}
if(wz==-1)
continue;
if(wz!=i)
{
jg=md-jg;
for(int j=0;j<n;j++)
{
int t=sz[i][j];
sz[i][j]=sz[wz][j];
sz[wz][j]=t;
}
}
for(int j=i+1;j<n;j++)
{
int t=1ll*sz[j][i]*ksm(sz[i][i],md-2)%md;
for(int k=i;k<n;k++)
sz[j][k]=(sz[j][k]-1ll*sz[i][k]*t%md+md)%md;
}
}
for(int i=0;i<n;i++)
jg=1ll*jg*sz[i][i]%md;
return jg;
}
后缀数组
int sa[30010],x[60010],y[30010],sl[30010],ra[30010],hei[30010];
char zf[30010];
void getsa(int n)
{
for(int i=0;i<n;i++)
sl[x[i]=zf[i]]+=1;
for(int i=1;i<='z';i++)
sl[i]+=sl[i-1];
for(int i=n-1;i>=0;i--)
sa[--sl[x[i]]]=i;
int m='z';
for(int mi=1;mi<=n;mi*=2)
{
int s=0;
for(int i=n-mi;i<n;i++)
y[s++]=i;
for(int i=0;i<n;i++)
{
if(sa[i]>=mi)
y[s++]=sa[i]-mi;
}
for(int i=1;i<=m;i++)
sl[i]=0;
for(int i=0;i<n;i++)
sl[x[i]]+=1;
for(int i=1;i<=m;i++)
sl[i]+=sl[i-1];
for(int i=n-1;i>=0;i--)
sa[--sl[x[y[i]]]]=y[i];
m=1;
for(int i=0;i<n;i++)
{
if(i!=0&&(x[sa[i]]!=x[sa[i-1]]||x[sa[i]+mi]!=x[sa[i-1]+mi]))
m+=1;
y[sa[i]]=m;
}
if(m==n)
break;
for(int i=0;i<n;i++)
x[i]=y[i];
}
for(int i=0;i<n;i++)
ra[sa[i]]=i;
for(int i=0,h=0;i<n;i++)
{
if(ra[i]==0)
continue;
if(h>0)
h-=1;
int j=sa[ra[i]-1];
while(zf[i+h]==zf[j+h])
h+=1;
hei[ra[i]]=h;
}
}
后缀自动机
int fa[2000010],trs[2000010][26],len[2000010],sl=1,la=1;
void insert(int c)
{
int np=++sl,p=la;
len[np]=len[la]+1,la=np;
while(p!=0&&trs[p][c]==0)
{
trs[p][c]=np;
p=fa[p];
}
if(p==0)
fa[np]=1;
else
{
int q=trs[p][c];
if(len[q]==len[p]+1)
fa[np]=q;
else
{
int nq=++sl;
len[nq]=len[p]+1;
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(int i=0;i<26;i++)
trs[nq][i]=trs[q][i];
while(p!=0&&trs[p][c]==q)
{
trs[p][c]=nq;
p=fa[p];
}
}
}
}
费用流
#include <stdio.h>
int fr[1005],ne[10010],v[10010],w[10010],fy[10010],bs=0;
int jl[1005],dl[400010],N,S,T,inf=99999999;
bool bk[1005];
void add(int a,int b,int c,int d)
{
v[bs]=b;
w[bs]=c;
fy[bs]=d;
ne[bs]=fr[a];
fr[a]=bs++;
}
void addb(int a,int b,int c,int d)
{
add(a,b,c,d);
add(b,a,0,-d);
}
bool spfa()
{
int he=0,ta=1;
for(int i=1;i<=N;i++)
{
bk[i]=false;
jl[i]=inf;
}
dl[0]=S;jl[S]=0;
while(he<ta)
{
int u=dl[he];
bk[u]=false;
for(int i=fr[u];i!=-1;i=ne[i])
{
if(w[i]>0&&jl[u]+fy[i]<jl[v[i]])
{
jl[v[i]]=jl[u]+fy[i];
la[v[i]]=u;lb[v[i]]=i;
if(!bk[v[i]])
{
dl[ta++]=v[i];
bk[v[i]]=true;
}
}
}
he+=1;
}
return jl[T]<inf;
}
int feiyl(int &fei)
{
fei=0;
int liu=0;
while(spfa())
{
int t=T,zx=inf;
while(t!=S)
{
if(w[lb[t]]<zx)
zx=w[lb[t]];
t=la[t];
}
liu+=zx;
t=T;
while(t!=S)
{
w[lb[t]]-=zx;
w[lb[t]^1]+=zx;
fei+=zx*fy[lb[t]];
t=la[t];
}
}
return liu;
}
LCT+Splay
#include <stdio.h>
int c1[2010],c2[2010],fa[2010];
int wz[2010],qz[2010];
bool ld[2010];
void pu(int i)
{
wz[i]=wz[c1[i]];
if(qz[wz[c2[i]]]>qz[wz[i]])
wz[i]=wz[c2[i]];
if(qz[i]>qz[wz[i]])
wz[i]=i;
}
void pur(int x)
{
ld[x]=!ld[x];
int t=c1[x];
c1[x]=c2[x];
c2[x]=t;
}
void pd(int x)
{
if(ld[x])
{
if(c1[x]!=0)
pur(c1[x]);
if(c2[x]!=0)
pur(c2[x]);
ld[x]=false;
}
}
void zuox(int x)
{
int t=c2[x];
c2[x]=c1[t];fa[c1[t]]=x;
c1[t]=x;fa[t]=fa[x];
if(x==c1[fa[x]])c1[fa[x]]=t;
else if(x==c2[fa[x]])c2[fa[x]]=t;
fa[x]=t;
pu(x);pu(t);
}
void youx(int x)
{
int t=c1[x];
c1[x]=c2[t];fa[c2[t]]=x;
c2[t]=x;fa[t]=fa[x];
if(x==c1[fa[x]])c1[fa[x]]=t;
else if(x==c2[fa[x]])c2[fa[x]]=t;
fa[x]=t;
pu(x);pu(t);
}
void rotate(int x)
{
if(x==c1[fa[x]])
youx(fa[x]);
else
zuox(fa[x]);
}
bool isrt(int x)
{
return x!=c1[fa[x]]&&x!=c2[fa[x]];
}
void clean(int x)
{
if(!isrt(x))
clean(fa[x]);
pd(x);
}
void splay(int x)
{
clean(x);
while(!isrt(x))
{
if(isrt(fa[x]))
rotate(x);
else
{
int f=fa[x];
if((f==c1[fa[f]])==(x==c1[f]))
{
rotate(fa[x]);
rotate(x);
}
else
rotate(x);
}
}
}
void access(int x)
{
int y=0;
while(x!=0)
{
splay(x);
c2[x]=y;
pu(x);
y=x;x=fa[x];
}
}
void makert(int x)
{
access(x);
splay(x);
pur(x);
}
int findrt(int x)
{
access(x);
splay(x);
while(c1[x]!=0)
x=c1[x];
splay(x);
return x;
}
void link(int x,int y)
{
makert(x);
makert(y);
fa[x]=y;
}
void cut(int x,int y)
{
makert(x);
access(y);
splay(x);
c2[x]=fa[y]=0;
}
int getmax(int x,int y)
{
makert(x);
access(y);
splay(x);
return wz[x];
}
扩展卢卡斯
int qz[30][10010];
void dfs(int n,int &a,int &b,int x,int mi,int bh)
{
if(n==0)
{
a=1;b=0;
return;
}
dfs(n/x,a,b,x,mi,bh);
b+=n/x;
a=1ll*a*ksm(qz[bh][mi],n/mi,mi)%mi;
a=1ll*a*qz[bh][n%mi]%mi;
}
void exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
}
else
{
exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
}
int getws(int n,int x)
{
int rt=0;
while(n>0)
{
rt+=n/x;
n/=x;
}
return rt;
}
int getz(int n,int m,int x,int mi,int k,int bh)
{
if(getws(n,x)-getws(m,x)-getws(n-m,x)>=k)
return 0;
int a1,b1;dfs(n,a1,b1,x,mi,bh);
int a2,b2;dfs(n-m,a2,b2,x,mi,bh);
int a3,b3;dfs(m,a3,b3,x,mi,bh);
b1-=(b2+b3);
int x2,y2,x3,y3;
exgcd(a2,mi,x2,y2);
exgcd(a3,mi,x3,y3);
x2=(x2%mi+mi)%mi;
x3=(x3%mi+mi)%mi;
a1=1ll*a1*x2%mi*x3%mi;
return 1ll*a1*ksm(x,b1,mi)%mi;
}
int fj[30],mi[30],xs[30],cs[30],sl=0;
void getcrt(int p)
{
int tp=p;sl=0;
for(int i=2;1ll*i*i<=tp;i++)
{
if(tp%i==0)
{
fj[sl]=i;mi[sl]=1;cs[sl]=0;
while(tp%i==0)
{
tp/=i;
mi[sl]*=i;
cs[sl]+=1;
}
sl+=1;
}
}
if(tp!=1)
{
fj[sl]=mi[sl]=tp;
cs[sl++]=1;
}
for(int i=0;i<sl;i++)
{
int x,y;
exgcd(p/mi[i],mi[i],x,y);
x=(x%mi[i]+mi[i])%mi[i];
xs[i]=1ll*(p/mi[i])*x%p;
}
for(int i=0;i<sl;i++)
{
qz[i][0]=1;
for(int j=1;j<=mi[i];j++)
{
qz[i][j]=qz[i][j-1];
if(j%fj[i]!=0)
qz[i][j]=1ll*qz[i][j]*j%mi[i];
}
}
}
int C(int n,int m,int p)
{
if(n<0||m<0||m>n)
return 0;
int jg=0;
for(int i=0;i<sl;i++)
{
int rt=getz(n,m,fj[i],mi[i],cs[i],i);
jg=(jg+1ll*rt*xs[i])%p;
}
return jg;
}
trie图
void bfs()
{
int he=0,ta=1;
dl[0]=0;
while(he<ta)
{
int u=dl[he];
if(u==0||fa[u]==0)
fi[u]=0;
else
fi[u]=trs[fi[fa[u]]][fb[u]];
for(int i=0;i<94;i++)
{
if(trs[u][i])
dl[ta++]=trs[u][i];
else
trs[u][i]=trs[fi[u]][i];
}
he+=1;
}
}
FWT
void fwtor(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
sz[j+(i>>1)+k]=(sz[j+(i>>1)+k]+sz[j+k])%md;
}
}
}
void ifwtor(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
sz[j+(i>>1)+k]=(sz[j+(i>>1)+k]-sz[j+k]+md)%md;
}
}
}
void fwtand(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
sz[j+k]=(sz[j+k]+sz[j+(i>>1)+k])%md;
}
}
}
void ifwtand(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
sz[j+k]=(sz[j+k]-sz[j+(i>>1)+k]+md)%md;
}
}
}
void fwtxor(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
{
int a=sz[j+k],b=sz[j+(i>>1)+k];
sz[j+k]=(a+b)%md;
sz[j+(i>>1)+k]=(a-b+md)%md;
}
}
}
}
void ifwtxor(int sz[132000],int n)
{
for(int i=2;i<=n;i=(i<<1))
{
for(int j=0;j<n;j+=i)
{
for(int k=0;k<(i>>1);k++)
{
int a=sz[j+k],b=sz[j+(i>>1)+k];
sz[j+k]=1ll*(a+b)*inv%md;
sz[j+(i>>1)+k]=1ll*(a-b+md)*inv%md;
}
}
}
}
KD树
void update(int x)
{
if(bk[x])
zx[x]=inf,wz[x]=-1;
else
zx[x]=qz[x],wz[x]=x;
if(cl[x]!=0&&wz[cl[x]]!=-1&&zx[cl[x]]<=zx[x])
zx[x]=zx[cl[x]],wz[x]=wz[cl[x]];
if(cr[x]!=0&&wz[cr[x]]!=-1&&zx[cr[x]]<=zx[x])
zx[x]=zx[cr[x]],wz[x]=wz[cr[x]];
}
void pur(int x,int y)
{
if(ld[x]!=-1&&y>=ld[x])
return;
ld[x]=y;
if(qz[x]>y)qz[x]=y;
if(zx[x]>y)zx[x]=y;
}
void pushdown(int x)
{
if(ld[x]==-1)return;
if(cl[x]!=0)pur(cl[x],ld[x]);
if(cr[x]!=0)pur(cr[x],ld[x]);
ld[x]=-1;
}
void clean(int x)
{
if(fa[x]!=0)
clean(fa[x]);
pushdown(x);
}
void del(int x)
{
clean(x);
bk[x]=true;
for(int i=x;i!=0;i=fa[i])
update(i);
}
int buix(SPx sz[70010],int l,int r);
int buiy(SPx sz[70010],int l,int r);
void pushup(int rt)
{
if(cl[rt]!=0)
{
lx[rt]=min(lx[rt],lx[cl[rt]]);rx[rt]=max(rx[rt],rx[cl[rt]]);
ly[rt]=min(ly[rt],ly[cl[rt]]);ry[rt]=max(ry[rt],ry[cl[rt]]);
fa[cl[rt]]=rt;
}
if(cr[rt]!=0)
{
lx[rt]=min(lx[rt],lx[cr[rt]]);rx[rt]=max(rx[rt],rx[cr[rt]]);
ly[rt]=min(ly[rt],ly[cr[rt]]);ry[rt]=max(ry[rt],ry[cr[rt]]);
fa[cr[rt]]=rt;
}
}
bool fugai(int Lx,int Rx,int Ly,int Ry,int lx,int rx,int ly,int ry)
{
return Lx<=lx&&rx<=Rx&&Ly<=ly&&ry<=Ry;
}
bool fenli(int Lx,int Rx,int Ly,int Ry,int lx,int rx,int ly,int ry)
{
return Lx>rx||lx>Rx||Ly>ry||ly>Ry;
}
int X[70010],Y[70010];
int buix(SPx sz[70010],int l,int r)
{
if(l>=r)return 0;
qsort(sz+l,r-l,sizeof(SPx),cmpx);
int m=(l+r-1)>>1,rt=sz[m].i;
lx[rt]=rx[rt]=sz[m].x;
ly[rt]=ry[rt]=sz[m].y;
cl[rt]=buiy(sz,l,m);
cr[rt]=buiy(sz,m+1,r);
pushup(rt);
return rt;
}
int buiy(SPx sz[70010],int l,int r)
{
if(l>=r)return 0;
qsort(sz+l,r-l,sizeof(SPx),cmpy);
int m=(l+r-1)>>1,rt=sz[m].i;
lx[rt]=rx[rt]=sz[m].x;
ly[rt]=ry[rt]=sz[m].y;
cl[rt]=buix(sz,l,m);
cr[rt]=buix(sz,m+1,r);
pushup(rt);
return rt;
}
void songc(int i,int Lx,int Rx,int Ly,int Ry,int z)
{
if(ld[i]!=-1&&z>ld[i])
return;
if(fenli(Lx,Rx,Ly,Ry,lx[i],rx[i],ly[i],ry[i]))
return;
if(fugai(Lx,Rx,Ly,Ry,lx[i],rx[i],ly[i],ry[i]))
{
pur(i,z);
return;
}
pushdown(i);
if(fugai(Lx,Rx,Ly,Ry,X[i],X[i],Y[i],Y[i]))
{
if(qz[i]>z)
qz[i]=z;
update(i);
}
if(cl[i]!=0)
songc(cl[i],Lx,Rx,Ly,Ry,z);
if(cr[i]!=0)
songc(cr[i],Lx,Rx,Ly,Ry,z);
update(i);
}
欧拉回路
void dfs3(int u)
{
for(int i=fr[u];i!=-1;i=ne[i])
{
if(fr[u]==-1)break;//表已被清空
fr[u]=ne[fr[u]];//当前弧优化
if(!bk[i/2])
{
bk[i/2]=true;
dfs3(v[i]);
hl[sl++]=i;//回溯记录
}
}
}
线性基
for(int i=0;i<=50;i++)
zt[i]=-1;
for(int i=0;i<n;i++)
{
ll t=sz[i];
for(int j=50;j>=0;j--)
{
if(t&(1ll<<j))
{
if(zt[j]==-1)
{
zt[j]=t;
break;
}
else
t=(t^zt[j]);
}
}
}
ll jg=0;
for(int i=50;i>=0;i--)
{
if(zt[i]!=-1&&(jg^zt[i])>jg)
jg=(jg^zt[i]);
}
printf("%lld",jg);
强连通分量
int dfn[MN],low[MN],tm=0,scc[MN],ss=0,st[MN],tp=0;
void tarjan(int u)
{
dfn[u]=low[u]=++tm;
st[tp++]=u;
for(int i=fr[u];i!=-1;i=ne[i])
{
int t=v[i];
if(!dfn[t])
{
tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(!scc[t])
low[u]=min(low[u],dfn[t]);
}
if(dfn[u]==low[u])
{
ss+=1;
while(1)
{
scc[st[tp-1]]=ss;
tp-=1;
if(st[tp]==u)break;
}
}
}
FFT
#include <stdio.h>
#include <math.h>
struct cp
{
double a,b;
cp(){}
cp(double A,double B)
{
a=A;b=B;
}
};
cp operator+(cp x,cp y)
{
return cp(x.a+y.a,x.b+y.b);
}
cp operator-(cp x,cp y)
{
return cp(x.a-y.a,x.b-y.b);
}
cp operator*(cp x,cp y)
{
return cp(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
}
void FFT(cp sz[140000],int n,int lx)
{
double pi=acos(-1.0);
for(int i=0,t=0;i<n;i++)
{
if(i>t)
{
cp o=sz[i];
sz[i]=sz[t];
sz[t]=o;
}
for(int j=(n>>1);(t^=j)<j;j=(j>>1));
}
for(int h=2;h<=n;h=(h<<1))
{
cp wn(cos(2*pi*lx/h),sin(2*pi*lx/h));
for(int i=0;i<n;i+=h)
{
cp t,w(1,0);
for(int j=i;j<i+(h>>1);j++,w=w*wn)
{
t=w*sz[j+(h>>1)];
sz[j+(h>>1)]=sz[j]-t;
sz[j]=sz[j]+t;
}
}
}
if(lx==-1)
{
for(int i=0;i<n;i++)
{
sz[i].a/=n;
sz[i].b=0;
}
}
}
cp sz[140000];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int a;
scanf("%d",&a);
sz[i].a=a;
sz[i].b=0;
}
for(int i=1;;i=(i<<1))
{
if(i>=n)
{
n=i;
break;
}
}
FFT(sz,n,1);
FFT(sz,n,-1);
for(int i=0;i<n;i++)
printf("%d ",int(sz[i].a+0.2));
return 0;
}
Manacher
void man()
{
int ma=-1,wz=-1;
for(int i=0;i<n;i++)
{
cd[i]=1;
if(i<=ma)
{
cd[i]=cd[wz-(i-wz)];
if(i+cd[i]-1>ma)
cd[i]=ma-i+1;
}
while(i-cd[i]>=0&&i+cd[i]<n&&zf[i-cd[i]]==zf[i+cd[i]])
cd[i]+=1;
if(i+cd[i]-1>ma)
{
ma=i+cd[i]-1;
wz=i;
}
}
}
KM最优完美匹配
bool dfs(int u)
{
vg[u]=true;
for(int i=0;i<n;i++)
{
if(vb[i])//只访问一次
continue;
int t=exg[u]+exb[i]-sz[u][i];
if(t==0)//此边可用
{
vb[i]=true;
if(pp[i]==-1||dfs(pp[i]))
{
pp[i]=u;
return true;//找到增广路
}
}
else
{
if(t<sl[i])//更新最小下降值
sl[i]=t;
}
}
return false;
}
void KM()
{
for(int i=0;i<n;i++)
pp[i]=-1;
for(int i=0;i<n;i++)
{
exb[i]=0;
exg[i]=-inf;
for(int j=0;j<n;j++)
{
if(sz[i][j]>exg[i])
exg[i]=sz[i][j];
}
}//初始化
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
sl[j]=inf;
while(1)
{
for(int j=0;j<n;j++)
vg[j]=vb[j]=false;
if(dfs(i))
break;
int zx=inf;
for(int j=0;j<n;j++)
{
if(!vb[j]&&sl[j]<zx)
zx=sl[j];//寻找最小下降值
}
for(int j=0;j<n;j++)
{
if(vg[j])
exg[j]-=zx;
if(vb[j])
exb[j]+=zx;
else //更新最小下降值
sl[j]-=zx;
}
}
}
}