模板代码集合

· · 个人记录

开头

此为 \texttt{Lijunzhuo} 专用,未经许可,不准转载或抄袭。

另外,还为了夏令营。 --- ## 一,数论模板 ### 1. $\texttt{gcd}$ 模板: ```cpp int gcd(int a,int b) { while(b^=a^=b^=a%=b); return a; } long long gcd(long long a,long long b) { while(b^=a^=b^=a%=b); return a; } ``` #### 另加快速乘模板: ```cpp long long mul(long long a,long long b,long long mod) { return (__int128)a*b%mod; } ``` ### 2. 快速幂(KSM): ```cpp long long KSMans; long long KSM(long long a,long long b,long long p) { ans=1,a%=p; while(b) { if(b&1) KSMans=KSMans*a%p; b>>=1; a=a*a%p; } return KSMans; } ``` ### 3. 矩阵乘法+快速幂: ```cpp const int N=105,MOD=1e9+7; long long n,k; struct Matrix { long long M[N][N]; }; Matrix A,ANS; Matrix Mul(const Matrix& A,const Matrix& B,int a,int b,int c,long long m) { Matrix C; memset(C.M,0,sizeof(C.M)); for(int i=0;i<a;i++) for(int j=0;j<b;j++) for(int k=0;k<c;k++) C.M[i][k]=(C.M[i][k]+A.M[i][j]*B.M[j][k]%m)%m; return C; } Matrix Mul(const Matrix& A,const Matrix& B,int n,long long m) { return Mul(A,B,n,n,n,m); } Matrix qpow(Matrix n,long long m,long long p,int a) { Matrix C; for(int i=0;i<a;i++) for(int j=0;j<a;j++) if(i==j) C.M[i][j]=1; else C.M[i][j]=0; while(m) { if(m&1) C=Mul(C,n,a,p); n=Mul(n,n,a,p); m>>=1; } return C; } ``` ### 4. Exgcd模板: ```cpp void Exgcd(long long a,long long b,long long &x,long long &y) { if(!b) x=1,y=0; else Exgcd(b,a%b,y,x),y-=a/b*x; } ``` ### 5. 质数筛模板: #### (1). ```cpp const int N=100005; bool vis_prime[N]; int prime[N],tot; void getprime1(int n) { memset(vis_prime,true,sizeof(vis_prime)); tot=0; vis_prime[0]=vis_prime[1]=false; for(int i=2;i<=n;i++) { if(vis_prime[i]) { prime[++tot]=i; for(int j=i;j<=n;j+=i) vis_prime[j]=false; } } } void getprime2(long long n) { memset(vis_prime,true,sizeof(vis_prime)); tot=0; vis_prime[0]=vis_prime[1]=false; for(long long i=2;i*i<=n;i++) if(vis_prime[i]) for(long long j=i*i;j<=n;j+=i) vis_prime[j]=false; for(int i=2;i<=n;i++) if(vis_prime[i]) prime[++tot]=i; } ``` #### (2). ```cpp const int N=100005; int prime[N],tot; bitset<N>is_prime; void getprime3(int n) { is_prime.set(); is_prime.reset(0),is_prime.reset(1); for(int i=2;i<=n;i++) if(is_prime.test(i)) { prime[++tot]=i; for(int j=i*2;j<N;j+=i) is_prime.reset(j); } } void getprime4(long long n) { is_prime.set(); is_prime.reset(0),is_prime.reset(1); for(long long i=2;i*i<=n;i++) if(is_prime.test(i)) for(long long j=i*i;j<N;j+=i) is_prime.reset(j); for(int i=2;i<=n;i++) if(is_prime.test(i)) prime[++tot]=i; } ``` #### (3). ```cpp const int N=100005; bool vis_prime[N]; int prime[N],tot; void GetPrime(int n) { memset(vis_prime,true,sizeof(vis_prime)); tot=0; vis_prime[0]=vis_prime[1]=false; for(int i=2;i<=n;i++) { if(vis_prime[i]) prime[++tot]=i; for(int j=1;j<=tot&&i*prime[j]<=n;j++) { vis_prime[i*prime[j]]=false; if(i%prime[j]==0) break; } } } ``` ### 6. 筛φ: #### (1). ```cpp const int N=100005; int phi[N]; void Getphi(int n) { for(int i=1;i<=n;i++) phi[i]=i; for(int i=2;i<=n;i++) if(phi[i]==i) for(int j=i;j<=n;j+=i) phi[j]=phi[j]/i*(i-1); } ``` #### (2). ```cpp const int N=100005; bool is_prime[N]; int phi[N],prime[N],tot; void Getphi(int n) { memset(is_prime,true,sizeof(is_prime)); is_prime[0]=is_prime[1]=false; phi[1]=1; for(int i=2;i<=n;i++) { if(is_prime[i]) { prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot&&prime[j]*i<=n;j++) { is_prime[i*prime[j]]=false; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; }else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } ``` ### 7.Lucas ```cpp //lucas(n,m,p)=cm(n%p,m%p)*lucas(n/p,m/p,p) //lucas(x,0,p)=1,cm(a,b)=(a!/(a-b)!)^(p-2)mod p long long ans,p; long long A[1000005]; long long KSM(long long a,long long b,long long p) { ans=1; while(b) { if(b&1) ans=ans*a%p; b>>=1; a=a*a%p; } return ans; } long long C(long long n,long long m) { if(m>n) return 0; return (A[n]*KSM(A[m],p-2,p)%p*KSM(A[n-m],p-2,p)%p); } long long cm(long long a,long long b) { return KSM(C(b,a),p-2,p); } long long lucas(long long n,long long m,long long p) { if(!m) return 1; return C(n%p,m%p)*lucas(n/p,m/p,p)%p; } ``` --- ## 二,数据结构类模板 ### 1. 线段树模板: ```cpp const int N=100005,M=N<<2; int n,m,A[N],a,b,c,d; struct segment_tree { long long data,lazy; }XT[M]; void push_up(int k) { XT[k].data=XT[k<<1].data+XT[k<<1|1].data; } void change(int l,int r,int k,int a) { XT[k].data+=a*(r-l+1); XT[k].lazy+=a; } void push_down(int l,int r,int mid,int k) { if(l==r) return ; change(l,mid,k<<1,XT[k].lazy); change(mid+1,r,k<<1|1,XT[k].lazy); XT[k].lazy=0; } void build(int l,int r,int k) { if(l==r) { XT[k].data=A[l]; return ; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); push_up(k); } void change(int l,int r,int k,int s,int v) { if(l==r&&l==s) { XT[k].data=v; return ; } int mid=(l+r)>>1; if(s<=mid) change(l,mid,k<<1,s,v); else change(mid+1,r,k<<1|1,s,v); push_up(k); } long long query(int l,int r,int k,int s,int t) { if(l>=s&&r<=t) return XT[k].data; int mid=(l+r)>>1; push_down(l,r,mid,k); long long res=0; if(s<=mid) res+=query(l,mid,k<<1,s,t); if(t>mid) res+=query(mid+1,r,k<<1|1,s,t); return res; } void up_date(int l,int r,int k,int s,int t,int a) { if(l>=s&&r<=t) { change(l,r,k,a); return ; } int mid=(l+r)>>1; push_down(l,r,mid,k); if(s<=mid) up_date(l,mid,k<<1,s,t,a); if(t>mid) up_date(mid+1,r,k<<1|1,s,t,a); push_up(k); } ``` ### 2. 树状数组模板: ```cpp #define lowbit(x) x&-x const int N=500005; int AT[N],n; void change(int x,int a) { for(int i=x;i<=n;i+=lowbit(i)) AT[i]+=a; } int query(int x) { int res=0; for(int i=x;i>=1;i-=lowbit(i)) res+=AT[i]; return res; } ``` ### 3. 分块模板 ```cpp const int N=200005,M=1005; int siz,tot,bel[N],L[M],R[M]; long long A[N],val[M],add[M]; inline void init() { siz=sqrt(n); tot=n/siz+(n%siz>0); for(int i=1;i<=tot;i++) L[i]=(i-1)*siz+1,R[i]=min(i*siz,n); for(int i=1;i<=n;i++) bel[i]=(i-1)/siz+1; for(int i=1;i<=n;i++) val[bel[i]]+=A[i]; } inline void up_date(int l,int r,long long x) { int lb=bel[l],rb=bel[r]; if(lb==rb) for(int i=l;i<=r;i++) val[lb]+=x,A[i]+=x; else { for(int i=lb+1;i<=rb-1;i++) add[i]+=x,val[i]+=x*siz; for(int i=l;i<=R[lb];i++) val[lb]+=x,A[i]+=x; for(int i=L[rb];i<=r;i++) val[rb]+=x,A[i]+=x; } } inline void up_date(int k,long long x){val[bel[k]]+=x,A[k]+=x;} inline long long query(int l,int r) { int lb=bel[l],rb=bel[r]; long long querysum=0; if(lb==rb) for(int i=l;i<=r;i++) querysum+=A[i]+add[lb]; else { for(int i=lb+1;i<=rb-1;i++) querysum+=val[i]; for(int i=l;i<=R[lb];i++) querysum+=A[i]+add[lb]; for(int i=L[rb];i<=r;i++) querysum+=A[i]+add[rb]; } return querysum; } inline long long query(int k){return A[k]+add[bel[k]];} ``` ### 4. 平衡树模板 ```cpp #include<bits/stdc++.h> using namespace std; const int N=100005,INF=0x3f3f3f3f; int n,tot,root,op,x,ans; struct node { int val,rd,l,r,size,cnt; }T[N]; int create(int val) { T[++tot]={val,rand(),0,0,1,1}; return tot; } void push_up(int p) { T[p].size=T[T[p].l].size+T[T[p].r].size+T[p].cnt; } void zig(int &p)//右旋 { int q=T[p].l; T[p].l=T[q].r; T[q].r=p; p=q; push_up(T[p].r); push_up(p); } void zag(int &p)//左旋 { int q=T[p].r; T[p].r=T[q].l; T[q].l=p; p=q; push_up(T[p].l); push_up(p); } void build() { create(-INF); create(INF); root=1; T[1].r=2, push_up(root); if(T[2].rd>T[1].rd) zag(root); } void insert(int &p,int x) { if(p==0) p=create(x); else if(x==T[p].val) T[p].cnt++; else if(x<T[p].val) { insert(T[p].l,x); if(T[T[p].l].rd>T[p].rd) zig(p); } else if(x>T[p].val) { insert(T[p].r,x); if(T[T[p].r].rd>T[p].rd) zag(p); } push_up(p); } void remove(int &p,int x) { if(p==0) return ; if(x==T[p].val) { if(T[p].cnt>1) T[p].cnt--; else { if(T[p].l||T[p].r) { if(!T[p].r||T[T[p].l].rd>T[T[p].r].rd) { zig(p); remove(T[p].r,x); }else { zag(p); remove(T[p].l,x); } }else p=0; } } else if(x<T[p].val) remove(T[p].l,x); else if(x>T[p].val) remove(T[p].r,x); push_up(p); } int getrank(int p,int x) { if(!p) return 1; if(x==T[p].val) return T[T[p].l].size+1; else if(x<T[p].val) return getrank(T[p].l,x); else return T[T[p].l].size+T[p].cnt+getrank(T[p].r,x); } int getnum(int p,int rank) { if(p==0) return INF; if(rank<=T[T[p].l].size) return getnum(T[p].l,rank); else if(rank<=T[T[p].l].size+T[p].cnt) return T[p].val; else return getnum(T[p].r,rank-T[T[p].l].size-T[p].cnt); } int prev(int p,int x) { if(p==0) return -INF; if(x<=T[p].val) return prev(T[p].l,x); else return max(T[p].val,prev(T[p].r,x)); } int ne(int p,int x) { if(p==0) return INF; if(x>=T[p].val) return ne(T[p].r,x); else return min(T[p].val,ne(T[p].l,x)); } int main() { srand(time(0)); scanf("%d",&n); build(); while(n--) { scanf("%d%d",&op,&x); if(op==1) insert(root,x); else if(op==2) remove(root,x); else if(op==3) printf("%d\n",getrank(root,x)-1); else if(op==4) printf("%d\n",getnum(root,x+1)); else if(op==5) printf("%d\n",prev(root,x)); else printf("%d\n",ne(root,x)); } return 0; } /* 1.右旋 Zag / 左旋 Zig (1)右旋 Q=a[P].l a[P].l=a[Q].r a[Q].r=P root=Q (2)左旋 Q=a[P].r a[P].r=a[Q].l a[Q].l=P root=Q 2.插入 (1)按BST的插入方法,将插入元素X作为新的结点插入 (2)如果插入的是某节点p的左子树,则比较插入后其左子树根优先级 是否>p的优先级(堆值),如果>,则右旋 (3)如果插入的是某节点p的右子树,则比较插入后其右子树根优先级 是否>p的优先级(堆值),如果>,则左旋 3.删除 (1)如果要删除的点p是叶子,直接删 (2)如果要删除的点p,没有右子树,或者左子树根的优先级(堆值)> 其右子树根的优先级(堆值),则右旋 (3)其余情况左旋 4.找前驱 值为x的结点的前驱,指的是值小于X的最大值 对于结点p所对应的子树,如果: (1) x<=a[p].val 说明前驱在左子树上 (2) x>a[p].val 说明a[p].val可能是前驱,但答案也可能在右子树上 取二者的较大值 找后继方法类似 5.求值x对应的排名 对于结点p所对应的子树,如果 (1) x<a[p].val 说明x在左子树上,则直接在左子树继续找 (2) x>a[p].val 说明x在右子树上,则排名=p左子树大小+p结点+右子树 查找的结果 (3) x==a[p].val 说明找到了x,排名再加上x左子树的大小,再加1 6.求排名为rank的数 对于结点p所对应的子树,如果 (1) rank <= a[a[p].l].size 说明答案在左子树上 (2) 如果不满足条件1,但是满足 rank <= a[a[p].l].size+a[p].cnt 说明当前的结点p就是要找到排名为rank的结点 (3) 如果上述条件都不满足,说明答案在右子树上,到右子树上找 排名为rank-a[a[p].l].size-a[p].cnt的数 */ ``` ## 三,图、树论模板 ### 1 $\texttt{and}$ 2. 最短路 与 K 短路模板 ```cpp #include<bits/stdc++.h> using namespace std; const int N=1005; struct node { int v,z; bool operator<(const node&b)const { return z>b.z; } }; struct starnode { int v,nowz,sumz; bool operator<(const starnode&b)const { return sumz>b.sumz; } }; int n,m,s,t,k,G[N],cnt[N],vis[N]; vector<node>R1[N],R2[N]; void dij(int s) { memset(G,0x3f,sizeof(G)); G[s]=0; priority_queue<node>P; P.push({s,0}); while(!P.empty()) { node ph=P.top(); P.pop(); if(vis[ph.v]) continue; else vis[ph.v]=true; for(auto v:R2[ph.v]) if(G[v.v]>G[ph.v]+v.z) G[v.v]=G[ph.v]+v.z, P.push({v.v,G[v.v]}); } } int Astar(int s) { priority_queue<starnode>P; P.push({s,0,G[s]}); while(!P.empty()) { starnode ph=P.top(); P.pop(); cnt[ph.v]++; if(cnt[ph.v]==k) return ph.sumz; for(auto v:R1[ph.v]) if(cnt[v.v]<k) P.push({v.v,ph.nowz+v.z,ph.nowz+v.z+G[v.v]}); } return -1; } int main() { scanf("%d%d%d%d%d",&n,&m,&s,&t,&k); for(int i=1;i<=m;i++) { int u,v,z; scanf("%d%d%d",&u,&v,&z); R1[u].push_back({v,z}); R2[v].push_back({u,z}); } dij(t); printf("%d\n",Astar(s)); return 0; } ``` ### 3. $\texttt{Tarjan}
int n,m,dfn[N],low[N],si[N],id[N],inst[N],st[N];
int dfncnt,sit,stot;
vector<int>R[N];
void Tarjan(int u)
{
    dfn[u]=low[u]=++dfncnt,
    st[++stot]=u,inst[u]=1;
    for(auto v:R[u])
    {
        if(!dfn[v])
            Tarjan(v),
            low[u]=min(low[u],low[v]);
        else if(inst[v])
            low[u]=min(low[u],dfn[v]);  
    }
    if(dfn[u]==low[u])
    {
        ++sit;
        do{
            id[st[stot]]=sit;
            ++si[sit];
            inst[st[stot]]=0;
        }while(st[stot--]!=u);
    }
}

别忘了:

for(int i=1;i<=n;i++)
    R[0].push_back(i);

4. LCA

int n,m,s,up[N][M],dep[N];
vector<int>R[N];
void DFS(int fa,int u,int de)
{
    dep[u]=de,up[u][0]=fa;
    for(int i=1;i<M;i++)
        up[u][i]=up[up[u][i-1]][i-1];
    for(auto v:R[u])
    {
        if(v==fa) continue;
        DFS(u,v,de+1);
    }
}
int lca(int x,int y)
{
    if(dep[x]>dep[y])
        swap(x,y);
    int cha=dep[y]-dep[x];
    for(int i=0;i<M;i++)
        if(cha>>i&1)
            y=up[y][i];
    if(x==y) return x;
    for(int i=M-1;i>=0;i--)
        if(up[x][i]!=up[y][i])
            x=up[x][i],
            y=up[y][i];
    return up[x][0];
}

5. 最大流最小割问题:dinic

int n,m,s,t,used[N],level[N],iter[N];
struct node{int v,z,p;};
vector<node>G[N];
queue<int>Q;
void BFS(int u)
{
    memset(level,0,sizeof(level)); 
    Q.push(u),level[u]=1;
    while(!Q.empty())
    {
        int ph=Q.front();
        Q.pop();
        for(auto te:G[ph])
            if(!level[te.v]&&te.z>0)
            {
                level[te.v]=level[ph]+1;
                Q.push(te.v);
            }
    }
}
int DFS(int u,int t,int f)
{
    if(u==t) return f;
    for(int &i=iter[u];i<(int)G[u].size();i++)
    {
        auto &v=G[u][i]; 
        if(level[u]+1==level[v.v]&&v.z>0)
        {
            int d=DFS(v.v,t,min(f,v.z));
            if(d>0)
            {
                v.z-=d,
                G[v.v][v.p].z+=d;
                return d;
            }
        }
    }
    return 0;
}
int dinic(int s,int t)
{
    int ans=0;
    for(;;)
    {
        BFS(s);
        if(level[t]==0)
            break;
        memset(iter,0,sizeof(iter));
        while(1)
        {
            int p=DFS(s,t,INF);
            if(!p) break;
            else ans+=p;
        }
    }
    return ans;
}

本人太蒟了,打绷了,先挖个坑,立个 \texttt{flag},有时间在来打。