模板汇总

本博客所有模板都经过测试,保证正确。

归并排序

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e5+77;
int a[N],n,tmp[N];
void Sort(int l,int r)
{
    if(l==r) return;
    int mid=(l+r)>>1;
    Sort(l,mid);
    Sort(mid+1,r);
    int i=l,j=mid+1,t=l;
    bool start;
    while(i<=mid||j<=r)
    {
        if(i>mid) start=1;
        else
        if(j>r) start=0;
        else
        if(a[i]<=a[j]) start=0;
        else start=1;

        if(start) tmp[t++]=a[j++];
        else tmp[t++]=a[i++];
    }
    for(int i=l;i<=r;i++) a[i]=tmp[i];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     scanf("%d",&a[i]);
    Sort(1,n);
    for(int i=1;i<=n;i++)
     printf("%d ",a[i]);
    return 0; 
}

LCS

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
map <int,int> ma; 
int n,m;
int s1[300009],s2[300009];
int a[300009],low[300009],len;
int find(int l,int r,int z)
{
    int mid;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(low[mid]<=z)
         l=mid+1;
        else r=mid-1;
    }
    return l;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
      scanf("%d",&s1[i]);
    for(int i=1;i<=m;i++)
      scanf("%d",&s2[i]);
    for(int i=1;i<=m;i++)
      ma[s2[i]]=i;
    for(int i=1;i<=n;i++)
      a[i]=ma[s1[i]];
    int t=1;
    while(a[t]==0) t++;
    low[++len]=a[t];
    for(int i=2;i<=n;i++)
    {
        if(a[i]==0) continue;
        if(a[i]>low[len])
         low[++len]=a[i];
        else
         {
            //low[upper_bound(low+1,low+len+1,a[i])-low]=a[i];
            low[find(1,len,a[i])]=a[i];
         }
    }   
    printf("%d",len);
    return 0;

}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm> 
using namespace std;
const int N=1e5+77;
int n,f[N],a[N],b[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);

    for(int i=1;i<=n;i++) f[b[i]]=i,b[i]=0;
    for(int i=1;i<=n;i++) a[i]=f[a[i]];

    int len=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>b[len]) b[++len]=a[i];
        else b[upper_bound(b+1,b+len+1,a[i])-b]=a[i];
    }
    printf("%d\n",len);
    return 0;
} 

小B的询问(莫队)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath> 
using namespace std;
const int N=5e4+77;
struct Q{
    int qv,id,l,r;
}q[N];
int n,m,k,a[N],ans[N],cnt[N],sum;
bool cmp(Q x,Q y)
{
    if(x.qv==y.qv) return x.r<y.r;
    return x.qv<y.qv;
}
void add(int x)
{
    if(!x) return;
    sum-=cnt[x]*cnt[x];
    cnt[x]++;
    sum+=cnt[x]*cnt[x];
}
void del(int x)
{
    if(!x) return;
    sum-=cnt[x]*cnt[x];
    cnt[x]--;
    sum+=cnt[x]*cnt[x];
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int limit=sqrt(n+10);
    for(int i=1;i<=m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        q[i].l=l,q[i].r=r;
        q[i].qv=q[i].l/limit;
        q[i].id=i;
    } 
    sort(q+1,q+m+1,cmp);

    int l=0,r=0;
    for(int i=1;i<=m;i++)
    {
        while(r<q[i].r)
        {
            add(a[++r]);
        }
        while(r>q[i].r)
        {
            del(a[r--]);
        }
        while(l<q[i].l)
        {
            del(a[l++]);
        }
        while(l>q[i].l)
        {
            add(a[--l]);
        }

        ans[q[i].id]=sum;
    }
    for(int i=1;i<=m;i++)
     printf("%d\n",ans[i]);
    return 0;
}

并查集

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath> 
using namespace std;
const int N=1e4+77;
int n,m,f[N];
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        int fx=find(x),fy=find(y);
        if(opt==1)
        {
            if(fx==fy) continue;
            f[fx]=fy;
        }
        else
        {
            if(fx==fy) printf("Y\n");
            else printf("N\n");
        }
    } 
    return 0;
}

最小生成树

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int M=2e5+77;
const int N=5077;
struct E{
    int x,y,z;
}e[M];
int n,m,f[N],ans;
bool cmp(E a,E b)
{
    return a.z<b.z;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
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].x,&e[i].y,&e[i].z);
    }
    sort(e+1,e+m+1,cmp);

    int cnt=n;
    for(int i=1;i<=m;i++)
    {
        int fx=find(e[i].x),fy=find(e[i].y);
        if(fx==fy) continue;
        f[fx]=fy;
        ans+=e[i].z;
        cnt--;
        if(cnt==1) break;
    }
    if(cnt==1) printf("%d\n",ans);
    else printf("orz\n");
    return 0;
}

字符串hash

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int mo=1e9+7;
const int moo=1e9+9;
const int b1=31;
const int b2=29;
const int M=1507;
const int N=1e4+77; 
int n,ans;
struct H{
    LL a,b;
}q[N];
char s[M];
bool cmp(H x,H y)
{
    return x.a<y.a;
}
LL hash()
{
    LL h=0;
    int len=strlen(s);
    for(int i=0;i<len;i++)
     h=(h*b1%mo+s[i]-'0')%mo;
    return h;
}
LL Hash()
{
    LL h=0;
    int len=strlen(s);
    for(int i=0;i<len;i++)
     h=(h*b2%moo+s[i]-'0')%moo;
    return h;
}
int main()
{
    scanf("%d\n",&n);
    for(int i=1;i<=n;i++)
    {
        gets(s);
        q[i].a=hash();
        q[i].b=Hash();
    }
    q[0].a=q[0].b=-1;
    sort(q+1,q+n+1,cmp);
    for(int i=1;i<=n;i++)
      if(q[i].a!=q[i-1].a||q[i].b!=q[i-1].b)
        ans++;
    printf("%d\n",ans);
    return 0;
}

最短路spfa O(K*m/RP)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
const int N=1e4+77;
const int M=5e5+77;
const int inf=2147483647;
int n,m,s;
int head[N],nxt[M],to[M],cost[M],tot;
LL dis[N]; 
bool vis[N];
void add(int x,int y,int z)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    cost[tot]=z;
}
void spfa()
{
    queue <int> q;
    q.push(s);
    dis[s]=0;
    vis[s]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=nxt[i])
          if(dis[to[i]]>dis[x]+cost[i]){
            dis[to[i]]=dis[x]+cost[i];
            if(!vis[to[i]])
            {
                vis[to[i]]=1;
                q.push(to[i]);
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z); 
        if(i<=n) dis[i]=inf;
    }
    spfa();
    for(int i=1;i<=n;i++)
       printf("%lld ",dis[i]);
    return 0; 
}

最短路Dijsktra O(n^n)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
const int N=1e4+77;
const int M=5e5+77;
const int inf=2147483647;
int n,m,s;
int head[N],nxt[M],to[M],cost[M],tot;
LL dis[N]; 
bool vis[N];
void add(int x,int y,int z)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    cost[tot]=z;
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z); 
        if(i<=n) dis[i]=inf;
    }
    dis[s]=0;
    for(int i=1;i<n;i++)
    {
        int minn=inf,x=0;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&minn>dis[j])
             minn=dis[j],x=j;
        }
        if(!x) break;
        vis[x]=1;
        for(int j=head[x];j;j=nxt[j])
          if(dis[to[j]]>dis[x]+cost[j])
            dis[to[j]]=dis[x]+cost[j];
    }
    for(int i=1;i<=n;i++)
     printf("%d ",dis[i]);
    return 0;
}

树状数组(单点修改+区间求和)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
const int N=5e5+77;
int n,m;
LL a[N],b[N];
void update(int i,LL x)
{
    for(;i<=n;i+=i&(-i))
      b[i]+=x;
}
LL query(int x)
{
    LL s=0; 
    for(int i=x;i>=1;i-=i&(-i))
      s+=b[i];
    return s;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        update(i,a[i]);
    }
    for(int i=1;i<=m;i++)
    {
        int opt,x,y;
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%d%d",&x,&y);
            update(x,y);
        }
        else
        {
            scanf("%d%d",&x,&y);
            LL ans=query(y);
            ans-=query(x-1);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

线段树 1 区间修改+区间求和

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define LL long long
using namespace std;
const int N=1e5+77; 
struct H{
    LL sum,ad;
    int len;
}z[4*N];
int n,m,a[N];
void build(int o,int l,int r)
{
    if(l==r){
        z[o].sum=a[l];
        z[o].len=r-l+1;
        return;
    }
    int mid=(l+r)>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
    z[o].sum=z[o<<1].sum+z[o<<1|1].sum;
    z[o].len=r-l+1;
}
void push_down(int o)
{
    if(z[o].ad)
    {
        LL ad=z[o].ad;
        z[o<<1].sum+=ad*z[o<<1].len;
        z[o<<1|1].sum+=ad*z[o<<1|1].len; 
        z[o<<1].ad+=ad;
        z[o<<1|1].ad+=ad;
        z[o].ad=0;
    }
}
LL query(int o,int l,int r,int ql,int qr)
{
    if(ql>r||qr<l) return 0;
    if(ql<=l&&qr>=r) return z[o].sum;

    push_down(o);

    int mid=(l+r)>>1;
    LL s=0;
    s+=query(o<<1,l,mid,ql,qr);
    s+=query(o<<1|1,mid+1,r,ql,qr);
    return s;
}
void change(int o,int l,int r,int ql,int qr,LL add)
{
    if(ql>r||qr<l) return;
    if(ql<=l&&qr>=r) 
    {
        z[o].sum+=add*z[o].len;
        z[o].ad+=add;
        return;
    } 

    push_down(o);

    int mid=(l+r)>>1; 
    change(o<<1,l,mid,ql,qr,add);
    change(o<<1|1,mid+1,r,ql,qr,add); 
    z[o].sum=z[o<<1].sum+z[o<<1|1].sum;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);

    build(1,1,n);

    for(int i=1;i<=m;i++)
    {
        int opt,l,r,k;
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%d%d%d",&l,&r,&k);
            change(1,1,n,l,r,k);    
        }
        else
        {
            scanf("%d%d",&l,&r);
            LL ans=query(1,1,n,l,r);
            printf("%lld\n",ans);
        }
    }
    return 0;
} 

ST表

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e5+77;
int n,m,a[N],ans;
int MAX[N][20];
int main()
{ 
    //freopen("b.txt","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),MAX[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i<=n;i++)
        {
            if(i+(1<<j)-1<=n)
            MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<j-1)][j-1]);
        }
    }
    for(int i=1;i<=m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        int t=log2(r-l+1);
        ans=max(MAX[l][t],MAX[r-(1<<t)+1][t]);
        printf("%d\n",ans);
    }
    return 0;
}

KMP

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1000007;
int nxt[N],len1,len2,ans[N],cnt;
char a[N],b[N];
void next_make()
{
    int i=0,j=-1;
    nxt[0]=-1;
    while(i<len2)
    {
        if(j==-1||b[i]==b[j])
          nxt[++i]=++j;
        else 
          j=nxt[j];
    }
}
void match(int i,int j)
{
    while(i<len1)
    {
        while(j<len2&&i<len1)
        {
            if(j==-1||a[i]==b[j])
             i++,j++;
            else j=nxt[j];
        }
        if(j==len2) ans[++cnt]=i-len2+1,j=nxt[j];
    }
}
int main()
{
    cin>>a;len1=strlen(a);
    cin>>b;len2=strlen(b);

    next_make();
    match(0,0);
    for(int i=1;i<=cnt;i++)
     printf("%d\n",ans[i]);
    for(int i=1;i<=len2;i++)
     printf("%d ",nxt[i]);
    return 0;
}

线性乘法逆元

证明

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define LL long long 
using namespace std;
const int N=3e6+7;
LL n,p,a[N];
int main()
{
    scanf("%lld%lld",&n,&p);
    a[1]=1;
    printf("%d\n",a[1]);
    for(int i=2;i<=n;i++)
    {
        a[i]=-(p/i)*(a[p%i]);
        a[i]=(a[i]%p+p)%p;
        printf("%lld\n",a[i]);
    } 
    return 0;
}

Tarjan求LCA

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define LL long long 
using namespace std;
const int N=500007;
int n,m,s;
int head[N],nxt[2*N],to[2*N],tot;
int qhead[N],qnxt[2*N],qto[2*N],qtot,lca[2*N];
int f[N];
bool vis[N];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
void qadd(int x,int y)
{
    qto[++qtot]=y;
    qnxt[qtot]=qhead[x];
    qhead[x]=qtot;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]); 
}
void dfs(int x)
{
    f[x]=x;
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i])
    {
        if(!vis[to[i]])
        {
            dfs(to[i]);
            f[to[i]]=x;
        }
    }
    for(int i=qhead[x];i;i=qnxt[i])
    {
        if(vis[qto[i]])
        {
            lca[i]=find(qto[i]);
            if(i%2) lca[i+1]=lca[i];
            else lca[i-1]=lca[i];
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }

    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        qadd(x,y);qadd(y,x);
    }

    dfs(s);

    for(int i=1;i<=m;i++)
    {
        printf("%d\n",lca[2*i]);
    }
    return 0;
}

倍增求LCA

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define LL long long 
using namespace std;
const int N=500007;
int n,m,s;
int head[N],nxt[2*N],to[2*N],tot;
int dep[N],f[N][22];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
void dfs(int x,int father)
{
    for(int i=head[x];i;i=nxt[i])
    {
        if(to[i]==father) continue;
        dep[to[i]]=dep[x]+1;
        f[to[i]][0]=x;
        dfs(to[i],x); 
    }
}
int find(int x,int y)
{
    if(x==y) return x; 
    if(dep[x]<dep[y]) swap(x,y);
    int i,j;
    for(i=20;i>=0;i--)
    {
        if(dep[x]==dep[y]) break;
        if(f[x][i])
          if(dep[f[x][i]]>=dep[y])
            x=f[x][i];
    }

    if(x==y) return x;

    for(i=20;i>=0;i--)
    {   
        if(f[x][i]&&f[y][i]&&f[x][i]!=f[y][i])//一直跳到下一步就能汇合
            x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }

    dfs(s,0);

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

    for(int i=1;i<=m;i++)
    {
        int x,y,ans;
        scanf("%d%d",&x,&y);
        ans=find(x,y);
        printf("%d\n",ans); 
    }
    return 0;
}

Tarjan缩点+树形dp(也可以用spfa)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long 
using namespace std;
const int N=1e4+7;
const int M=1e5+7;
int n,m,a[N];
int head[N],nxt[M],to[M],tot;
int color[N],dfn[N],low[N],dfs_num,color_num,stack[N],top;
int cnt[N],sum[N],f[N];
bool vis[N];
LL ans,son_max[N];
int X[M],Y[M];
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
void dfs(int x)
{
    stack[++top]=x;
    dfn[x]=++dfs_num;
    low[x]=dfs_num;
    vis[x]=1;

    for(int i=head[x];i;i=nxt[i])
    {
        if(!dfn[to[i]])
        {
            dfs(to[i]);
            low[x]=min(low[x],low[to[i]]);
        }
        else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    }

    if(low[x]==dfn[x])
    {
        vis[x]=0;
        color[x]=++color_num;
        cnt[color_num]++;
        sum[color_num]+=a[x];
        while(stack[top]!=x)
        {
            vis[stack[top]]=0;
            color[stack[top]]=color_num;
            cnt[color_num]++;
            sum[color_num]+=a[stack[top]];
            top--;
        }
        top--;
    }
}
LL DFS(int x)
{
    LL s=sum[x],p=0;
    for(int i=head[x];i;i=nxt[i])
    {
        p=max(p,(son_max[to[i]])?son_max[to[i]]:son_max[to[i]]=DFS(to[i]));
    }
    return son_max[x]=s+p;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        X[i]=x;
        Y[i]=y;//记下原图关系 
    }

    for(int i=1;i<=n;i++)
     if(!dfn[i]) dfs(i);

    memset(nxt,0,sizeof(nxt));
    memset(to,0,sizeof(to));
    memset(head,0,sizeof(head));
    tot=0;

    for(int i=1;i<=m;i++)
    {
        if(color[X[i]]!=color[Y[i]])
        add(color[X[i]],color[Y[i]]);
    }

    for(int i=1;i<=color_num;i++)
    {
         ans=max(ans,DFS(i));
    }

    printf("%lld\n",ans);
    return 0;
}

二分图最大匹配(匈牙利算法)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1009;
int match[2*N];
bool book[2*N];
int head[2*N],nxt[N*N],to[N*N],tot;
int n,m,e,ans;
void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
int dfs(int x)
{
    for(int i=head[x];i;i=nxt[i])
    {
        if(!book[to[i]])
        {
            book[to[i]]=1;
            if(!match[to[i]]||dfs(match[to[i]]))
            {
                match[x]=to[i];
                match[to[i]]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&e);
    for(int i=1;i<=e;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        if(v>m) continue;
        add(u,v+n);add(v+n,u);
    }

    for(int i=1;i<=n;i++)
    {
        memset(book,0,sizeof(book));
        ans+=dfs(i);
    }
    printf("%d\n",ans);
    return 0; 
} 

dfs_spfa判断负环

其思想是:采用广度优先的思想,每当我们扩展出一个新的节点,总是把它放到队列的末尾,其缺点是中断了迭代的连续性。而实际上如果采用深度优先的思想,我们可以直接从这个新节点继续往下扩展。于是算法的实现方式可以改成不断从新节点往下递归进行求解。 而对于负环的判断则显得更为简单,因为假如存在负环a1->a2->….ak->a1,那么算法运行时,会从某个点a1开始Dfs,最后又回到了这个点。所以只需用一个辅助数组记录当前节点是否在递归栈中便可及时检测出负环。

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long 
using namespace std;
const int N=200007;
/*inline LL read()
{
    LL x,p=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') 
    {
        if(ch=='-') p=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'9',ch=getchar();
    return x*p;
}*/
int Q,n,m;
int head[N],nxt[2*N],to[2*N],cost[2*N],tot;
int dis[N];
bool vis[N],exist;
void add(int x,int y,int z)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    cost[tot]=z;
}
void init()
{
    memset(head,0,sizeof(head));
    memset(to,0,sizeof(to));
    memset(nxt,0,sizeof(nxt));
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    tot=0;
    exist=0;
}
void dfs_spfa(int x)
{
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i])
    {
        if(dis[to[i]]>dis[x]+cost[i])
        {
            if(vis[to[i]]) {
                exist=1;
                return;
            }
            dis[to[i]]=dis[x]+cost[i];
            dfs_spfa(to[i]);
        } 
    }
    vis[x]=0;
}
int main()
{
    scanf("%d",&Q);
    while(Q--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(z<0) add(x,y,z);
            else {
                add(x,y,z);
                add(y,x,z);
            }
        }
        for(int i=1;i<=n;i++)
        {
            dfs_spfa(i);
            if(exist) break;
        }
        if(exist) printf("YE5\n");
        else printf("N0\n");
    }
    return 0;
}

欧拉函数的线性筛(附带素数线性筛)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e7+7;
int prime[N],cnt,phi[N];
bool np[N];
void PHI()
{
    phi[1]=1;
    np[0]=1,np[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!np[i]) 
        {
            prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt&&1ll*i*prime[j]<N;j++)
        {
            np[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}
int main()
{
    PHI();
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      printf("%d\n",phi[i]);
    return 0;
}

同余方程

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    LL gcd=exgcd(b,a%b,x,y);
    LL tmp=x;
    x=y;
    y=tmp-a/b*y;
    return gcd;
}
int main()
{
    LL a,b,x,y;
    scanf("%lld%lld",&a,&b);
    LL gcd=exgcd(a,b,x,y);
    printf("%lld",(x+b)%b);
    return 0;
}

高精乘高精

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e4+7;
const int P=1e4;
char s1[N],s2[N];
int a[N],b[N],c[2*N];
int len1,len2,l1,l2;
int main()
{
    scanf("%s",s1);l1=strlen(s1);
    scanf("%s",s2);l2=strlen(s2);

    len1=len2=1;
    int x=1;
    for(int i=l1-1;i>=0;i--)
    {
        a[len1]+=(s1[i]-'0')*x;
        x=(x<<1)+(x<<3);
        if(x==P) x=1,++len1; 
    }
    x=1;
    for(int i=l2-1;i>=0;i--)
    {
        b[len2]+=(s2[i]-'0')*x;
        x=(x<<1)+(x<<3);
        if(x==P) x=1,++len2;
    }

    for(int i=1;i<=len1;i++)
    {
        x=0;
        for(int j=1;j<=len2;j++)
        {
            c[i+j-1]+=a[i]*b[j]+x;
            x=c[i+j-1]/P;
            c[i+j-1]%=P;
        }
        c[i+len2]+=x;
    }
    int len=len1+len2;
    while(len>1&&!c[len]) len--;

    printf("%d",c[len--]);
    for(int i=len;i>=1;i--)
     printf("%04d",c[i]);
    return 0;
}

低精除高精

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define LL long long
using namespace std;
const int P=1e9;
const int N=1e5;
char s[N];
LL a[N],b;
int main()
{
    scanf("%s%lld",s,&b);
    int L=strlen(s);
    LL k=1;int len=1;
    for(int i=L-1;i>=0;i--)
    {
        a[len]+=(s[i]-'0')*k;
        k=(k<<1)+(k<<3);
        if(k==P) k=1,++len;
    }
    for(int i=len;i>=1;i--)
    {
        a[i-1]+=a[i]%b*P;
        a[i]/=b;
    }
    while(len>=1&&!a[len]) len--;

    printf("%lld",a[len--]);
    for(int i=len;i>=1;i--)
     printf("%09d",a[i]);
    return 0;
} 

高精乘高精

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const int N=1e4+7;
const int P=1e4;
char s1[N],s2[N];
int a[N],b[N],c[2*N];
int len1,len2,l1,l2;
int main()
{
    scanf("%s",s1);l1=strlen(s1);
    scanf("%s",s2);l2=strlen(s2);

    len1=len2=1;
    int x=1;
    for(int i=l1-1;i>=0;i--)
    {
        a[len1]+=(s1[i]-'0')*x;
        x=(x<<1)+(x<<3);
        if(x==P) x=1,++len1; 
    }
    x=1;
    for(int i=l2-1;i>=0;i--)
    {
        b[len2]+=(s2[i]-'0')*x;
        x=(x<<1)+(x<<3);
        if(x==P) x=1,++len2;
    }

    for(int i=1;i<=len1;i++)
    {
        x=0;
        for(int j=1;j<=len2;j++)
        {
            c[i+j-1]+=a[i]*b[j]+x;
            x=c[i+j-1]/P;
            c[i+j-1]%=P;
        }
        c[i+len2]+=x;
    }
    int len=len1+len2;
    while(len>1&&!c[len]) len--;

    printf("%d",c[len--]);
    for(int i=len;i>=1;i--)
     printf("%04d",c[i]);
    return 0;
}

矩阵快速幂(多次询问离线)

蒟蒻不会重载运算符qwq

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
const int MOD=1e9+7;
LL A[4][4]={
    0,0,0,0,
    0,1,1,0,
    0,0,0,1,
    0,1,0,0,};
LL ans[5][5],tmp[5][5],b[107],B[5][5],C[5][5];
int n;
struct H{
    int id,x;
}q[107];
bool cmp(H a,H b)
{
    return a.x<b.x;
}
LL q_pow(LL p)
{
    p--;
    for(int i=1;i<=3;i++) for(int j=1;j<=3;j++) B[i][j]=C[i][j]=A[i][j];
    while(p)
    {
        if(p&1)
        {
            for(int i=1;i<=3;i++)
             for(int j=1;j<=3;j++)
              tmp[i][j]=B[i][j],B[i][j]=0;
            for(int i=1;i<=3;i++)
             for(int j=1;j<=3;j++)
              for(int k=1;k<=3;k++)
               (B[i][j]+=(tmp[i][k]*C[k][j])%MOD)%=MOD;
        }
        for(int i=1;i<=3;i++)
           for(int j=1;j<=3;j++)
              tmp[i][j]=C[i][j],C[i][j]=0;
        for(int i=1;i<=3;i++)   
          for(int j=1;j<=3;j++)
            for(int k=1;k<=3;k++)
              (C[i][j]+=(tmp[i][k]*tmp[k][j])%MOD)%=MOD;
        p>>=1;
    }
    for(int i=1;i<=3;i++)
     for(int j=1;j<=3;j++)
       tmp[i][j]=ans[i][j],ans[i][j]=0;
     for(int i=1;i<=3;i++)  
      for(int j=1;j<=3;j++)
       for(int k=1;k<=3;k++)
        (ans[i][j]+=(tmp[i][k]*B[k][j])%MOD)%=MOD;
    return ans[1][1];
}
int main()
{
    scanf("%d",&n);
    ans[1][1]=1,ans[1][2]=1,ans[1][3]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&q[i].x);
        q[i].id=i;
    }
    sort(q+1,q+n+1,cmp);

    bool first=1;
    for(int i=1;i<=n;i++)
    {
        if(q[i].x<=3)
        {
            b[q[i].id]=1;
            continue;
        }
        if(first) b[q[i].id]=q_pow(q[i].x-3),first=0;
        else
        {
            if(q[i].x==q[i-1].x) b[q[i].id]=b[q[i-1].id];
            else 
            b[q[i].id]=q_pow(q[i].x-q[i-1].x);
        }
    }
    for(int i=1;i<=n;i++)
     printf("%lld\n",b[i]);
    return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值