代码模板库

图论

tarjan+缩点:

//有向图tarjan缩点
void add(int a,int b)
{
    bian[++ecnt].to=b;
    bian[ecnt].nxt=head[a];
    head[a]=ecnt;
}
void add1(int a,int b)//函数名称容易出锅,以后要用有区分度的名称
{
    tu[++rcnt].to=b;
    tu[rcnt].nxt=headtu[a];
    headtu[a]=rcnt;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++tim;//
    stk[++tk]=u;//入栈
    vis[u]=true;//入栈标记
    for(int i=head[u];i;i=bian[i].nxt)
    {
        int v=bian[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[v],low[u]);
        }
        else if(vis[v])//注意这附近的if else 括号匹配,多次出锅
            low[u]=min(low[v],low[u]);
    }
    if(dfn[u]==low[u])
    {
        num++;
        while(stk[tk]!=u)
        {
            vis[stk[tk]]=false;
            shuyu[stk[tk]]=num;
            stk[tk]=0;
            tk--;
        }//可以用do while代替,用while的话执行完要再来一次
        vis[stk[tk]]=false;
        shuyu[stk[tk]]=num;//记录属于哪个联通块
        stk[tk]=0;//出栈
        tk--;
    }
}
void suo()//枚举点和边,原来的边左右两点如果不在同一联通块,则建新边
{
    for(int i=1;i<=n;i++)
    {
        int u=shuyu[i];
        shd[u]+=dian[i];
        for(int j=head[i];j;j=bian[j].nxt)
        {
            int v=bian[j].to;
            if(shuyu[v]!=u)
            {
                add1(u,shuyu[v]);
            }
        }
    }
}
int main()
{
    n=read();m=read();
    int a,b;
    for(int i=1;i<=n;i++)
        dian[i]=read();
    for(int i=1;i<=m;i++)
    {
        a=read();b=read();
        add(a,b);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])//注意这里,整个图不一定是连通图,所以要遍历整个图
            tarjan(i);
    }
    suo();//缩点
    for(int i=1;i<=num;i++)
        ans=max(ans,dfs(i));
    cout<<ans;
    return 0;
}
View Code

tarjan求点双:

void tarjan(int x)
{
    dfn[x]=low[x]=++tim;
    int flag=0;
    for(int i=head[x];i;i=bian[i].nxt)
    {
        int y=bian[i].to;
        if(!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x])
            {
                flag++;
                if((x!=rof||flag>1)&&gee[x]==0)
                    ge[++cnt]=x,gee[x]=1;//you chong fu
            }
        }
        else low[x]=min(low[x],dfn[y]);
    }
}

~int main
for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            rof=i,tarjan(i);
    }
View Code

tarjan求边双:

void tarjan(int u,int bian)
{
    dfn[u]=low[u]=++tim;
    for(int i=head[u];i;i=bian[i].nxt)
    {
        int v=bian[i].to;
        if(!dfn[v])
        {
            tarjan(v,i);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u])
                isbridge[i]=isbridge[i^1]=1;
        }
        else if(i!=(bian^1))
            low[u]=min(low[u],dfn[v]);
    }
} 
~int main
for(int i=1;i<=n;i++)
    if(!dfn[i])
        tarjan(i,0); 
View Code

最小生成树(prim):

//prim
void prim()
{
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    int b=1;
    for(int j=1;j<=n;j++)
    {
        vis[b]=true;cnt++;ans+=dis[b];
        for(int i=head[b];i;i=bian[i].nxt)
        {
            int c=bian[i].to;
            int d=bian[i].quan;
            if(d<dis[c])dis[c]=d;
        }
        mx=0x3f3f3f3f;
        for(int i=1;i<=n;i++)
        {
            if(dis[i]<mx&&vis[i]==false)
            {
                mx=dis[i];
                b=i;
            }
        }
    }
}
View Code

 最短路(dijstra):

void dij()
{
    memset(dis,0x3f,sizeof(dis));
    int qi=s;
    dis[qi]=0;
    q.push(bbb{qi,0});
    while(!q.empty())
    {
        bbb w=q.top();
        int k=w.jiedian;
        q.pop();
        if(!vis[k])
        {
            vis[k]=true;
            for(int i=head[k];i;i=bian[i].nxt)
            {
                int v=bian[i].to;
                if(dis[v]>dis[k]+bian[i].leng)
                {
                    dis[v]=dis[k]+bian[i].leng;
                    q.push(bbb{v,dis[v]});
                }
            }
        }
    }
}
View Code

最短路(SPFA):(忘了急需复习

#include<bits/stdc++.h>
using namespace std;
int n,m,s;
int a,b,c;
int dis[100005];
bool vis[100005];
int head[100005],ecnt;
struct aaa
{
    int jiedian,dis;
};
bool operator <(const aaa& a,const aaa& b){
    return a.dis>b.dis;
}
priority_queue<aaa>q;
struct edge{
    int to,nxt,dis;
}ed[200010];
void addedge(int f,int to,int dis)
{
    ed[++ecnt].to=to;
    ed[ecnt].dis=dis;
    ed[ecnt].nxt=head[f];
    head[f]=ecnt;
}
inline int read()
{
    int x=0;
    char c=getchar();
    bool flag=0;
    while(c<'0'||c>'9'){if(c=='-')flag=1;   c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?-x:x;
}
void suanfa()
{
    memset(dis,0x3f,sizeof dis);
    int k=s;
    dis[s]=0;
    for(int i=head[k];i!=0;i=ed[i].nxt)
            {
                int v=ed[i].to;//ed xianduan
                if(dis[v]>dis[k]+ed[i].dis)
                {
                    q.push(aaa{ed[i].to,dis[k]+ed[i].dis});
                    dis[v]=dis[k]+ed[i].dis;
                }
                    
            }
    while(!q.empty())
    {
        aaa w=q.top();
        int k=w.jiedian;
        q.pop();
        if(vis[k]==false)
        {
            vis[k]=true;//mark white;
            for(int i=head[k];i!=0;i=ed[i].nxt)
            {
                int v=ed[i].to;//ed xianduan
                if(dis[v]>dis[k]+ed[i].dis)
                {
                    q.push(aaa{ed[i].to,dis[k]+ed[i].dis});
                    dis[v]=dis[k]+ed[i].dis;
                }
            }
        }
    }
}
int main()
{
    n=read();m=read();s=read();
    for(int i=1;i<=m;i++)
    {
        a=read();b=read();c=read();
        addedge(a,b,c);
    }
    suanfa();
    for(int i=1;i<=n;i++)
    {
        if(dis[i]!=0x3f3f3f3f)
            printf("%d ",dis[i]);
        else cout<<2147483647<<" ";
    }
    return 0;
}
View Code 

倍增lca:

#include<bits/stdc++.h>
using namespace std;
int n,m,s;
int a,b;
struct aaa
{
    int to,nxt;
}bian[1000001];
int head[500001];
int ecnt;
int deep[500001];
bool vis[500001];
int dian[500001][20];
int deepmax;

inline int read()
{
    int x=0;
    char c=getchar();
    bool flag=0;
    while(c<'0'||c>'9'){if(c=='-')flag=1;   c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?-x:x;
}

void dfs(int a)
{
    for(int i=head[a];i;i=bian[i].nxt)
    {
        int b=bian[i].to;
        if(!deep[b])
        {
            deep[b]=deep[a]+1;
            dian[b][0]=a;
            dfs(b);
        }
    }
}

void st()
{
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            {
                if(dian[i][j-1]) dian[i][j]=dian[dian[i][j-1]][j-1];
            }
}

void add(int a,int b)
{
    bian[++ecnt].to=b;
    bian[ecnt].nxt=head[a];
    head[a]=ecnt;
    bian[++ecnt].to=a;
    bian[ecnt].nxt=head[b];
    head[b]=ecnt;
}

int lca(int a,int b)
{
    if(deep[a]<deep[b])swap(a,b);
    int i;
    for(i=0;(1<<i)<=deep[a];i++);
    i--;
    for(int j=i;j>=0;j--)
    {
        if(deep[a]-(1<<j)>=deep[b])
        {
            a=dian[a][j];
        }
    }
    if(a==b)return a;
    for(int j=i;j>=0;j--)
    {
        if(dian[a][j]!=0&&dian[a][j]!=dian[b][j])
        {
            a=dian[a][j];
            b=dian[b][j];
        }
    }
    return dian[a][0];
}

int main()
{
    n=read();m=read();s=read();
    for(int i=1;i<=n-1;i++)
    {
        a=read();b=read();
        add(a,b);
    }
    dian[s][0]=0;
    deep[s]=1;//初始化深度; 
    dfs(s);//求深度;
    st();
    for(int i=1;i<=m;i++)
    {
        a=read();b=read();
        int c=lca(a,b);
    //    if(a==s||b==s)cout<<s<<endl;
    //    else
        printf("%d
",c);
    }
    return 0;
}
View Code

数学

 线性筛:

//线性筛
bool sushu[10000005];
int n,m;
int sushubiao[5000005];
int q;
void shai()
{
    for(int i=2;i<=n;i++)
    {
        if(!sushu[i])
            sushubiao[++q]=i;
        for(int j=1;j<=q&&sushubiao[j]*i<=n;j++)
        {
            sushu[sushubiao[j]*i]=true;
            if(i%sushubiao[j]==0)break;
        }
    }
}
View Code

乘法逆元:

void ny()
{
    inv[1]=1;
    for(int i=2;i<=n;i++)
        inv[i]=1ll*(p-(p/i))*inv[p%i]%p;
}
a^p-2===a^-1 (mod p)
View Code

高斯消元:

#include<bits/stdc++.h>
using namespace std;
const double jd=5e-3;
int n;
double fc[55][55];
double xi[55];
double jie[55];
inline int read()
{
    int x=0;bool f=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return f?-x:x;
}
void Gauss()
{
    for(int i=1;i<=n-1;i++)//消第i个未知数; 
    {
        for(int j=i+1;j<=n;j++)
        {
            if(fc[i][i]==0)
            {
                for(int k=1;k<=n;k++)
                {
                    swap(fc[i][k],fc[j][k]);
                }
                swap(xi[i],xi[j]);
            }
            if(abs(fc[j][i])<jd)
                continue;
            double cun=fc[i][i]/fc[j][i];
            for(int k=i;k<=n;k++)
                fc[j][k]=fc[j][k]*cun-fc[i][k];
            xi[j]=xi[j]*cun-xi[i];
        }
    }
}
int jfc()
{
    for(int i=n;i>=1;i--)
    {
        double zuo=0,you=xi[i];
        for(int j=n;j>i;j--)
            zuo+=fc[i][j]*jie[j];
        you-=zuo;
        if(abs(fc[i][i])<jd&&abs(you)>jd)return -1;
        if(abs(fc[i][i])<jd&&abs(you)<jd)return 0;
        jie[i]=you/fc[i][i];
    }
    return 1;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            fc[i][j]=read()*1.0;
        xi[i]=read()*1.0;
    }
    Gauss();
    switch(jfc())
    {
        case 1:
        {
            for(int i=1;i<=n;i++)
            {
                if(abs(jie[i])<jd)printf("x%d=0
",i);
                else printf("x%d=%.2lf
",i,jie[i]);
            }
                
            break;
        }
        case 0://无穷多解
        {
            cout<<0<<endl;
            break;
        }
        case -1://无解
        {
            cout<<-1<<endl;
            break;
        }
    }
}
View Code

exgcd:

void exgcd(ll a,ll b)
{
    if(b==0)
    {
        x=1;y=0;
        return;
    }
    exgcd(b,a%b);
    ll tem=x;
    x=y;
    y=tem-a/b*y;
}
View Code

扩展中国剩余定理(excrt):

#include<bits/stdc++.h>
using namespace std;
#define ll __int128
ll ans,x,y,a,b,c,yu[100005],mo[100005],M,n;
long long read()
{
    ll f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}
long long gcd(ll a,ll b)
{
    ll c;
    while(a%b)
    {
        c=a%b;
        a=b;
        b=c;
    }
    return b;
}
long long lcm(ll a,ll b)
{
    return a/gcd(a,b)*b;
}
void exgcd(ll a,ll b)
{
    if(b==0)
    {
        x=1;y=0;
        return;
    }
    exgcd(b,a%b);
    ll tem=x;
    x=y;
    y=tem-a/b*y;
}
long long excrt()
{
    M=mo[1];ans=yu[1];
    for(int i=2;i<=n;i++)
    {
        exgcd(M,mo[i]);
        ll gcdd=gcd(M,mo[i]);
        if((yu[i]-ans)%gcdd!=0)return -1;
        x*=(yu[i]-ans)/gcdd;
        ans=ans+x*M;
        M=M/gcd(M,mo[i])*mo[i];
        ans=(ans%M+M)%M;
    }
    return ans;
}
int main()
{
    n=read();
    for(ll i=1;i<=n;i++)
        mo[i]=read(),yu[i]=read();
    cout<<excrt();
    return 0;
}
View Code

卢卡斯定理:(小模数的组合数)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int T;
ll n,m,p;
ll a[100005];
inline ll read()
{
    bool f=0;ll x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return f?-x:x;
}
ll ks(ll x,ll k)
{
    ll num=1;
    while(k)
    {
        if(k&1)
            num=num*x%p;
        x=x*x%p;
        k>>=1;
    }
    return num;
}
ll c(ll n,ll m)
{
    if(m>n)return 0;
    return ((a[n]*ks(a[m],p-2))%p*ks(a[n-m],p-2)%p);
}
ll lucas(ll n,ll m)
{
    if(!m)return 1;
    return c(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main()
{
    T=read();
    while(T--)
    {
        n=read();m=read();p=read();
        a[0]=1;
        for(int i=1;i<=p;i++)a[i]=(a[i-1]*i)%p;
        cout<<lucas(n+m,n)<<endl;
    }
    return 0;
}
View Code

数据结构

树状数组

//树状数组
int lowb(int x){return x&-x;}
void add(int x,int k)
{
    for(;x<=n;x+=lowb(x))
        s[x]+=k;
}
long long ask(int a)
{
    long long ans=0;
    while(a!=0)
    {
        ans+=s[a];
        a-=lowb(a); 
    }
    return ans;
}
//询问l~r: ans=ask(r)-ask(l-1)
View Code

线段树

//这是线段树1,如果有乘法,先乘后加即可。
//还有一些线段树的题,是线段树结构和标记的巧妙应用
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m;
int a[N];
struct aaa
{
    int l,r;
    long long sum,lazy;
}t[4*N];
inline int read()
{
    int x=0;bool flag=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=true;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?-x:x;
}
void build(int num,int l,int r)
{
    t[num].l=l;t[num].r=r;
    if(l==r)
    {
        t[num].sum=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(num*2,l,mid);
    build(num*2+1,mid+1,r);
    t[num].sum=t[num*2].sum+t[num*2+1].sum;
}
void push(int num)
{
    t[2*num+1].sum+=t[num].lazy*(t[2*num+1].r-t[2*num+1].l+1);
    t[2*num+1].lazy+=t[num].lazy;
    t[2*num].sum+=t[num].lazy*(t[2*num].r-t[2*num].l+1);
    t[2*num].lazy+=t[num].lazy;
    t[num].lazy=0;
}
void add(int l,int r,int zhi,int num)
{
    int x=t[num].l,y=t[num].r;
    if(x==l&&y==r)
    {
        t[num].lazy+=zhi;
        t[num].sum+=(r-l+1)*zhi;
        return;
    }    
    int mid=(x+y)/2;
    push(num);
    if(r<=mid)
        add(l,r,zhi,2*num);
    else if(l>mid)
        add(l,r,zhi,2*num+1);
    else
    {
        add(l,mid,zhi,2*num);
        add(mid+1,r,zhi,2*num+1);
    }
    t[num].sum=t[2*num].sum+t[2*num+1].sum;
}
long long ask(int l,int r,int num)
{
    int x=t[num].l,y=t[num].r;
    if(x==l&&y==r)return t[num].sum;
    int mid=(x+y)/2;
    if(t[num].lazy)push(num);
    if(r<=mid)
        return ask(l,r,2*num);
    else if(l>mid)
        return ask(l,r,2*num+1);
    else return ask(l,mid,2*num)+ask(mid+1,r,2*num+1);    
}
int main()
{
    n=read();m=read();
    int e,b,c,d;
    for(int i=1;i<=n;i++)
        a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        e=read();
        if(e==1)
        {
            b=read();c=read();d=read();
            add(b,c,d,1);
        }
        else if(e==2)
        {
            b=read();c=read();
            long long ans=ask(b,c,1);
            printf("%lld
",ans);
        }
    }
    return 0;
}
View Code

其他 

st表:不修改的区间内求最大最小值(无法求和)

//st表模板
//不修改的区间求最大最小值,无法求和
//st[i][j]表示从i开始(包括i),之后2^j的区间内的最大/最小值
 for(int i=1;i<=n;i++)//对于自身的预处理
        mx[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++)//先循环2的j次方,否则信息不全无法合并。
        for(int i=1;i+(1<<j)-1<=n;i++)//i+(1<<j)-1<=n,注意要减1,(想意思)
        {
            mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
        }
    for(int i=1;i<=m;i++)//查询
    {
        b=read();c=read();
        k=log2(c-b+1);//查询是2的几次方
        ans=max(mx[b][k],mx[c-(1<<k)+1][k]));//由于k是向下取整,所以要这样做避免少算。    
    }
View Code

 快速幂:

ll ksm(ll x,ll k)
{
    ll num=1;
    while(k)
    {
        if(k&1)
            num=num*x%p;
        x=x*x%p;
        k>>=1;
    }
    return num%p;
}
View Code

三分:

//如果是整数定义域,边界很难处理
while(r-l>=mn)
    {
        double a=(2*l+r)/3,b=(l+2*r)/3;
        if(f(a)>f(b))
            r=b;
        else l=a;
    }
View Code

哈希:

for(int i=1;i<=n;i++)
    {
        scanf("%s",a[i]+1);
        int q=strlen(a[i]+1);
        for(int j=1;j<=q;j++)    
            hsh[i]=(hsh[i]*139+a[i][j])%100000007;    
    }
View Code

a

原文地址:https://www.cnblogs.com/oierjzy/p/11318013.html