各种模板

最短路

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=2e6+5;
const int inf=0x7fffffff;
int h[maxn],vis[maxn],dis[maxn];
int tot,n,m,s;
struct edge
{
    int u;//next
    int v;//to
    int w;//weight
}e[maxm];
struct node
{
    int now;
    int w;
    bool operator<(const node&a)const
    {
        return w>a.w;
    }
};
inline void add(int u,int v,int w)
{
    tot++;
    e[tot].v=v;
    e[tot].w=w;
    e[tot].u=h[u];
    h[u]=tot;
}
inline void dijkstra()
{
    for(int i=1;i<=n;++i)
    {
        dis[i]=inf;
    }
    dis[s]=0;
    priority_queue<node> que;
    que.push((node){s,0});
    while(!que.empty())
    {
        node x=que.top();
        que.pop();
        int u=x.now;
        if(vis[u])continue;
        vis[u]=1;
        for(int i=h[u];i;i=e[i].u)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                que.push((node){v,dis[v]});
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;++i)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    dijkstra();
    for(int i=1;i<=n;++i)
    {
        printf("%d ",dis[i]);
    }
    return 0;
}
dijkstra

 最小生成树

#include <bits/stdc++.h>
using namespace std;
const int inf=0x7fffffff;
const int maxn=5e3+5;
const int maxm=2e5+5;
int h[maxn],dis[maxn],vis[maxn];
int n,m,tot,cnt,ans,now=1;
struct edge
{
    int u;
    int v;
    int w;
}e[maxm<<1];
inline void add(int u,int v,int w)
{
    tot++;
    e[tot].v=v;
    e[tot].w=w;
    e[tot].u=h[u];
    h[u]=tot;
}
inline int prim()
{
    for(int i=2;i<=n;++i)
    {
        dis[i]=inf;
    }
    for(int i=h[1];i;i=e[i].u)
    {
        dis[e[i].v]=min(dis[e[i].v],e[i].w);
    }
    while(++cnt<n)
    {
        int mmin=inf;
        vis[now]=1;
        for(int i=1;i<=n;++i)
        {
            if(!vis[i]&&mmin>dis[i])
            {
                mmin=dis[i];
                now=i;
            }
        }
        ans+=mmin;
        for(int i=h[now];i;i=e[i].u)
        {
            int v=e[i].v;
            if(!vis[v]&&dis[v]>e[i].w)
            {
                dis[v]=e[i].w;
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    printf("%d\n",prim());
    return 0;
}
prim
#include <bits/stdc++.h>
using namespace std;
const int inf=0x7fffffff;
const int maxn=5e3+5;
const int maxm=2e5+5;
int f[maxn];
int n,m,eu,ev,cnt,ans;
struct edge
{
    int u;
    int v;
    int w;
}e[maxm];
inline bool cmp(const edge&a,const edge&b)
{
    return a.w<b.w;
}
inline int find_(int x)
{
    return f[x]==x?x:f[x]=find_(f[x]);
}
inline void kruskal()
{
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;++i)
    {
        eu=find_(e[i].u);
        ev=find_(e[i].v);
        if(eu==ev)continue;
        ans+=e[i].w;
        f[ev]=eu;
        if(++cnt==n-1)break;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)f[i]=i;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    }
    kruskal();
    printf("%d\n",ans);
    return 0;
}
kruskal

 字符串

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int kmp[N];
char a[N],b[N];
int main()
{
    scanf("%s%s",a+1,b+1);
    int alen=strlen(a+1);
    int blen=strlen(b+1);
    for(int i=2,j=0;i<=blen;++i)
    {
        while(j&&b[i]!=b[j+1])j=kmp[j];
        if(b[i]==b[j+1])j++;
        kmp[i]=j;
    }
    for(int i=1,j=0;i<=alen;++i)
    {
        while(j&&a[i]!=b[j+1])j=kmp[j];
        if(a[i]==b[j+1])j++;
        if(j==blen)
        {
            printf("%d\n",i-blen+1);
            j=kmp[j];
        }
    }
    for(int i=1;i<blen;++i)
    {
        printf("%d ",kmp[i]);
    }
    printf("%d\n",kmp[blen]);
    return 0;
}
kmp
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int tree[N][30];
bool flag[N];
int tot;
inline bool insert_(string s)
{
    int len=s.size();
    int rt=0;
    int id;
    for(int i=0;i<len;++i)
    {
        if(s[i]>='a'&&s[i]<='z')id=s[i]-'a';
        if(tree[rt][id]==0)tree[rt][id]=++tot;
        rt=tree[rt][id];
    }
    int mark=flag[rt];
    flag[rt]=1;
    return !mark;
}
inline bool find_(char *s)
{
    int len=strlen(s);
    int rt=0;
    int id;
    for(int i=0;i<len;++i)
    {
        if(s[i]>='a'&&s[i]<='z')id=s[i]-'a';
        if(tree[rt][id]==0)return 0;
        rt=tree[rt][id];
    }
    return flag[rt];
}
int main()
{
    ios::sync_with_stdio(false);
    while(1)
    {
        tot=0;
        memset(tree,0,sizeof(tree));
        memset(flag,0,sizeof(flag));
        int ans=0;
        string a;
        getline(cin,a);
        stringstream ss(a);
        int i=0;
        while(ss>>a)
        {
            if(a[0]=='#'&&i==0)return 0;
            ans+=insert_(a);
            ++i;
        }
        printf("%d\n",ans);
    }
}
trie
#include <bits/stdc++.h>
using namespace std;
const int N=61100000;
char a[N],s[N<<1];
int n,hw[N],mmax=1;
inline void change()
{
    s[0]=s[1]='#';
    for(int i=0;i<n;++i)
    {
        s[i*2+2]=a[i];
        s[i*2+3]='#';
    }
    n=n*2+2;
    s[n]=0;
}
void manacher()
{
    int maxright=0,mid;
    for(int i=1;i<n;i++)
    {
        if(i<maxright)hw[i]=min(hw[(mid<<1)-i],maxright-i);
        else hw[i]=1;
        for(;s[i+hw[i]]==s[i-hw[i]];++hw[i]);
        if(hw[i]+i>maxright)
        {
            maxright=hw[i]+i;
            mid=i;
        }
        mmax=max(mmax,hw[i]);
    }
}
int main()
{
    scanf("%s",a);
    n=strlen(a);
    change();
    manacher();
    cout<<mmax-1;
    return 0;
}
manacher
#include <bits/stdc++.h>
#define maxn 1000005
using namespace std;
int tree[maxn][26];
int val[maxn];
int fail[maxn];
int cnt=0;
inline void build(char *s)
{
    int len=strlen(s);
    int now=0;
    for(int i=0;i<len;++i)
    {
        int v=s[i]-'a';
        if(tree[now][v]==0)tree[now][v]=++cnt;
        now=tree[now][v];
    }
    val[now]++;
}
inline void get_fail()
{
    queue<int>q;
    for(int i=0;i<26;++i)
    {
        if(tree[0][i])
        {
            fail[tree[0][i]]=0;
            q.push(tree[0][i]);
        }
    }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<26;++i)
        {
            if(tree[u][i])
            {
                fail[tree[u][i]]=tree[fail[u]][i];
                q.push(tree[u][i]);
            }
            else tree[u][i]=tree[fail[u]][i];
        }
    }
}
inline int ac_query(char *s)
{
    int len=strlen(s);
    int now=0,ans=0;
    for(int i=0;i<len;++i)
    {
        now=tree[now][s[i]-'a'];
        for(int k=now;k&&val[k]!=-1;k=fail[k])
        {
            ans+=val[k];
            //val[k]=-1;
        }
    }
    return ans;
}
struct sss
{
    char s[10001];
}ss[100003];
char str[maxn];
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        memset(val,0,sizeof(val));
        memset(tree,0,sizeof(tree));
        memset(fail,0,sizeof(fail));
        for(int i=1;i<=n;++i)
        {
            scanf("%s",ss[i].s);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%s",str);
            build(str);
        }
        get_fail();
        for(int i=1;i<=n;++i)
        {
            printf("%d\n",ac_query(ss[i].s));
        }
    }
    return 0;
}
/*
5
she
he
say
shr
her
yasherhs
*/
ac自动机

ST表

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
int st[50][100010];
inline int Max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    ios::sync_with_stdio(false);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;++i)
    {
        cin>>st[0][i];
    }
    int t=log2(n);
    for(int i=1;i<=t;++i)
    {
        for(int j=1;j+(1<<i)-1<=n;++j)
        {
            st[i][j]=Max(st[i-1][j],st[i-1][j+(1<<(i-1))]);
        }
    }
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        int t=log2(r-l+1);
        cout<<Max(st[t][l],st[t][r-(1<<t)+1])<<endl;
    }
    return 0;
}
st表

矩阵快速幂

#include <bits/stdc++.h>
using namespace std;
const int MOD=1e9+7;
const int maxn=110;
typedef long long ll;
ll n,kk;
struct mat
{
    ll m[maxn][maxn];
}c,d,e,o;
inline mat mul(const mat &a,const mat &b)
{
    mat ret=o;
    for(int i=1;i<=3;++i)
    {
        for(int j=1;j<=3;++j)
        {
            for(int k=1;k<=3;++k)
            {
               ret.m[i][j]=(ret.m[i][j]+a.m[i][k]*b.m[k][j]%MOD)%MOD;
            }
        }
    }
    return ret;
}
inline mat qpow(mat x,ll y)
{
    mat ans=e;
    while(y)
    {
        if(y&1)ans=mul(ans,x);
        x=mul(x,x);
        y>>=1;
    }
    return ans;
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=3;++i)
    {
        for(int j=1;j<=3;++j)
        {
            o.m[i][j]=0;
        }
        e.m[i][i]=1;
    }
    d=o;
    d.m[1][1]=1;
    d.m[1][2]=1;
    d.m[2][3]=1;
    d.m[3][1]=1;
    c=o;
    c.m[1][1]=1;
    c.m[1][2]=1;
    c.m[1][3]=1;
    for(int i=1;i<=n;++i)
    {
        scanf("%lld",&kk);
        if(kk<3)
        {
            printf("1\n");
            continue;
        }
        mat ans=qpow(d,kk-3);
        ans=mul(c,ans);
        printf("%lld\n",ans.m[1][1]);
    }
    return 0;
}
矩阵快速幂
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int n=1e6+5;
int vis[n],phi[n],p[n],cnt;
ll ans[n];
ll oula(ll n)
{
    ll res=n;
    for(ll i=2;i*i<=n;++i)
    {
        if(n%i==0)res=res/i*(i-1);
        while(n%i==0)n/=i;
    }
    if(n>1)res=res/n*(n-1);
    return res;
}
void oulashai()
{
    phi[1]=1;
    for(int i=2;i<=n;++i)
    {
        if(vis[i]==0)//i为素数
        {
            p[++cnt]=i;//将i加入素数数组p中
            phi[i]=i-1;//因为i是素数,由特性得知
        }
        for(int j=1;j<=cnt&&i*p[j]<=n;++j)  //用当前已得到的素数数组p筛,筛去p[j]*i
        {
            vis[i*p[j]]=1;//可以确定i*p[j]不是素数
            if(i%p[j]==0) //看p[j]是否是i的约数,因为素数p[j],等于判断i和p[j]是否互质
            {
                phi[i*p[j]]=phi[i]*p[j]; //特性2
                break;
            }
            else phi[i*p[j]]=phi[i]*phi[p[j]];//(p[j]-1); //互质,特性3其,p[j]-1就是phi[p[j]]
        }
    }
}
//m[i]标记i是否为素数,0为素数,1不为素数;p是存放素数的数组;nump是当前素数个数;phi[i]为欧拉函数
int main()
{
    oulashai();
    int t;
    for(int i=1;i<=n;++i)
    {
        ans[i]=ans[i-1]+phi[i];
    }
    while(~scanf("%d",&t)&&t)
    {
        cout<<ans[t]-1<<endl;
    }
    return 0;
}
欧拉函数

数论

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
ll f[50];
ll c[50][50];
ll ff[40];
inline void init()
{
    f[1]=0;
    f[2]=1;
    for(int i=3;i<=35;++i)
    {
        f[i]=(i-1)*(f[i-1]+f[i-2]);
    }
    c[0][0]=1;
    for(int i=1;i<=35;++i)
    {
        for(int j=0;j<=i;++j)
        {
            c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
    }
    ff[0]=ff[1]=1;
    for(int i=2;i<=35;++i)
    {
        for(int j=0;j<i;++j)
        {
            ff[i]+=ff[j]*ff[i-j-1];
        }
    }
}
int main()
{
    init();
    int t;
    int cnt=0;
    while(~scanf("%d",&t))
    {
        if(t==-1)break;
        printf("%d %d %lld\n",++cnt,t,ff[t]*2);
    }
    return 0;
}
卡特兰数错排组合数

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define lowbit(i)(i&(-i))
#define Max(a,b)(((a)>(b))?(a):(b))
#define Min(a,b)(((a)<(b))?(a):(b))
using namespace std;
const int maxn=200010;
typedef long long ll;
ll a[maxn];//原数据
ll c1[maxn];//记录区间增量
ll c2[maxn];
ll asum[maxn];//差分原数据
ll mmax[maxn];
ll mmin[maxn];
int n,m;
inline void add(ll *arr,int x,ll val)//修改节点
{
    while(x<=n)
    {
        arr[x]+=val;
        x+=lowbit(x);
    }
}
inline void qj_add(int l,int r,ll val)//区间修改 运用了差分的思想
{
    add(c1,l,val);
    add(c1,r+1,-val);
    add(c2,l,val*l);//*1
    add(c2,r+1,-val*(r+1));
}
inline ll sum(ll *arr,ll x)
{
    ll ans=0;
    while(x)
    {
        ans+=arr[x];
        x-=lowbit(x);
    }
    return ans;
}
inline ll F(int x)
{
    return asum[x]+(x+1)*sum(c1,x)-sum(c2,x);
}
inline ll query(int l,int r)//区间查询
{
    return F(r)-F(l-1);
}
inline int max_query(int l,int r)
{
    int ans=a[r];
    while(l!=r)
    {
        r--;
        while(r-l>=lowbit(r))
        {
            ans=Max(ans,mmax[r]);
            r-=lowbit(r);
        }
        ans=Max(ans,a[r]);
    }
    return ans;
}
inline int min_query(int l,int r)
{
    int ans=a[r];
    while(l!=r)
    {
        r--;
        while(r-l>=lowbit(r))
        {
            ans=Min(ans,mmin[r]);
            r-=lowbit(r);
        }
        ans=Min(ans,a[r]);
    }
    return ans;
}
inline void update(int x,ll val)
{
    a[x]=val;
    while(x<=n)
    {
        mmax[x]=a[x];
        mmin[x]=a[x];
        for(int j=1;j<lowbit(x);j<<=1)
        {
            mmax[x]=Max(mmax[x],mmax[x-j]);
            mmin[x]=Min(mmin[x],mmin[x-j]);
        }
        x+=lowbit(x);
    }
}
树状数组
#include <bits/stdc++.h>
using namespace std;
const int maxn=200005;
typedef long long ll;
double sum[maxn<<2];
double pls[maxn<<2];
double mul[maxn<<2];
int n,m;
inline void pushup(int rt)//往上更新区间和
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void build(int rt,int l,int r)
{
    if(l==r)
    {
        scanf("%lf",&sum[rt]);
        return;
    }
    mul[rt]=1;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
inline void pushdown(int rt,int l,int r)
{
    int mid=(l+r)>>1;
    sum[rt<<1]*=mul[rt];
    mul[rt<<1]*=mul[rt];
    pls[rt<<1]*=mul[rt];
    sum[rt<<1|1]*=mul[rt];
    mul[rt<<1|1]*=mul[rt];
    pls[rt<<1|1]*=mul[rt];
    sum[rt<<1]+=pls[rt]*(mid-l+1);
    pls[rt<<1]+=pls[rt];
    sum[rt<<1|1]+=pls[rt]*(r-mid);
    pls[rt<<1|1]+=pls[rt];
    pls[rt]=0;
    mul[rt]=1;
}
inline void add_qj(int rt,int l,int r,int ql,int qr,double k)//区间加
{
     if(ql<=l&&r<=qr)
     {
        sum[rt]+=k*(r-l+1);
        pls[rt]+=k;
        return;
     }
     pushdown(rt,l,r);
     int mid=(l+r)>>1;
     if(ql<=mid)add_qj(rt<<1,l,mid,ql,qr,k);
     if(qr>mid)add_qj(rt<<1|1,mid+1,r,ql,qr,k);
     pushup(rt);
}
inline void mul_qj(int rt,int l,int r,int ql,int qr,double k)//区间乘
{
    if(ql<=l&&r<=qr)
    {
        sum[rt]*=k;
        mul[rt]*=k;
        pls[rt]*=k;
        return;
    }
    pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if(ql<=mid)mul_qj(rt<<1,l,mid,ql,qr,k);
    if(qr>mid)mul_qj(rt<<1|1,mid+1,r,ql,qr,k);
    pushup(rt);
}
double query(int rt,int l,int r,int ql,int qr)//单点查询
{
   if(ql<=l&&r<=qr)return sum[rt];
   pushdown(rt,l,r);
   int mid=(l+r)>>1;
   double sum1=0,sum2=0;
   if(ql<=mid)sum1+=query(rt<<1,l,mid,ql,qr);
   if(qr>mid)sum2+=query(rt<<1|1,mid+1,r,ql,qr);
   return sum1+sum2;
}
int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--)
    {
        int opt;
        scanf("%d",&opt);
        if(opt==1)
        {
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            double l1=b-a+1,l2=d-c+1;
            double s1=query(1,1,n,a,b);
            double s2=query(1,1,n,c,d);
            mul_qj(1,1,n,a,b,(l1-1)/l1);
            mul_qj(1,1,n,c,d,(l2-1)/l2);
            add_qj(1,1,n,a,b,1.0/l1*(s2/l2));
            add_qj(1,1,n,c,d,1.0/l2*(s1/l1));
        }
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%.5f\n",query(1,1,n,a,b));
        }
    }
    return 0;
}
新线段树
 背包
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define Max(a,b)(((a)>(b))?(a):(b))
using namespace std;
const int maxn=100010;
const int inf=0x3f3f3f3f;
int f[maxn],c[maxn],w[maxn];
inline void completepack(int v,int w,int m)
{
    for(int j=v;j<=m;++j)
    {
        f[j]=Max(f[j],f[j-v]+w);
    }
}
inline void zeroonepack(int v,int w,int m)
{
    for(int j=m;j>=v;--j)
    {
        f[j]=Max(f[j],f[j-v]+w);
    }
}
inline void multipack(int v,int w,int m,int c)
{
    if(v*c>m)
    {
        completepack(v,w,m);
    }
    else
    {
        int k=1;
        while(k<c)
        {
            zeroonepack(k*v,k*w,m);
            c-=k;
            k*=2;
        }
        zeroonepack(c*v,c*w,m);
    }
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)
        {
            return 0;
        }
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&w[i]);//
        }
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&c[i]);//
        }
        for(int i=1;i<=n;++i)
        {
            multipack(w[i],w[i],m,c[i]);
        }
        int sum=0;
        for(int i=1;i<=m;++i)
        {
            if(f[i]==i)
            {
                ++sum;
            }
        }
        printf("%d\n",sum);///
    }
    return 0;
}
背包
原文地址:https://www.cnblogs.com/yoududezongzi/p/11368456.html