各种简单的困难的模板,持续更新

本文涵盖邻接表、矩阵乘法、欧拉筛、快速幂等算法的代码实现,涉及图论、线性代数、数论及最短路径等领域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大部分模板为代码片段,可能有少部分的完整程序


邻接表

struct os
{
    int fa,son,next,v;
}a[100000];//边数
int first[10000]//点数
//定义

void add(int x,int y,int z)
{
    a[++tot].fa=x;
    a[tot].son=y;
    a[tot].v=z;
    a[tot].next=first[x];
    first[x]=tot;
}
……
    for (int i=1;i<=m;i++)
    scanf("%d%d%d",&x,&y,&z),
    add(x,y,z),
    //add(y,x,z);有向图时不用这条
//建边
for (int i=first[x];i;i=a[i].next)
……
//调用所有以x为出点的边

矩阵乘法(mod为取模数)

struct matrix
{
    int map[130][130];
};
matrix mul(matrix a,matrix b)
{
    matrix c;
    memset(c.map,0,sizeof(c.map));
    for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    for (int k=1;k<=n;k++)
    c.map[i][j]=(c.map[i][j]+(a.map[i][k]*b.map[k][j]%mod))%mod;
    return c;
}

矩阵快速幂(配合上面使用)

matrix qr(matrix a,int b)
{
    matrix c;
    c=a;
    b--;
    while (b)
    {
        if (b&1) c=mul(c,a);
        a=mul(a,a);
        b>>=1;
    }
    return c;
}

普通快速幂

int qr(int x,int y,int z)
{
    int ans=1;
    x%=z;
    while (y)
    {
        if (y&1) ans=ans*x%z;
        x=x*x%z;
        y>>=1;
    }
    return ans;
}

欧拉筛(求1-n的phi和质数)


    int prime[1000000],phi[1000000]
    ……
    phi[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!pd[i])
        prime[++prime[0]]=i,phi[i]=i-1;
        for (int j=1;j<=prime[0];j++)
        {
            if (prime[j]*i>n) break;
            pd[prime[j]*i]=1;
            if (i%prime[j]==0) {phi[i*prime[j]]=phi[i]*prime[j];break;}
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }

求逆元

void exgcd(int a,int b,int &x,int &y)
{
    if (b==0) {x=1;y=0;return;}
    exgcd(b,a%b,x,y);
    int x1=y,y1=x-a/b*y;
    x=x1;y=y1;
}
int getinv(int p)
{
    int x,y;
    exgcd(p,r,x,y);
    return (x%r+r)%r;
}

位运算小技巧:http://blog.csdn.net/xym_csdn/article/details/50725540
Lucas定理

……
#define LL long long
……
LL lucas(LL p,LL q,LL num)
{
    LL sum=1;
    while (p&&q)
    {
        LL x=p%prime[num],y=q%prime[num];
        if (y>x) return 0;
        sum=(sum*(fac[x]*qr(fac[y]*fac[x-y],prime[num]-2,prime[num]))%prime[num])%prime[num];
        p/=prime[num];
        q/=prime[num];
    }
    return sum;
}
……
for (LL j=1;j<=prime[i];j++)
 fac[j]=fac[j-1]*j%mod;

SPFA(邻接表)

#include<bits/stdc++.h>
using namespace std; 
struct os
{
    int fa,son,next,w;
}a[100010];
bool flag[10010];
int first[10010],tot,dis[10010],n,m,x,y,z;
queue <int>q;
void add(int x,int y,int z)
{
    a[++tot].fa=x;
    a[tot].son=y;
    a[tot].w=z;
    a[tot].next=first[x];
    first[x]=tot;
}
main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    scanf("%d%d%d",&x,&y,&z),
    add(x,y,z);
//  add(y,x,z);//是无向图就去掉注释
    memset(dis,63,sizeof(dis));
    dis[1]=0;
    q.push(1);
    flag[1]=1;
    while (!q.empty())
    {
        int t=q.front();
        flag[t]=0;
        q.pop();
        for (int i=first[t];i;i=a[i].next)
        {
            int p=a[i].son;
            if (dis[t]+a[i].w<dis[p])
            {
                dis[p]=dis[t]+a[i].w;
                if (!flag[p]) q.push(p),flag[p]=1;
            }
        }
    }
    printf("%d",dis[n]);
}

快速读入

int in()
{
    int f=1,t=0;
    char ch=getchar();
    while (ch>'9'||ch<'0')
    {
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();
    return f*t;
}

秦九韶算法

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int n,x,a[100000];
LL ans;
main()
{
    scanf("%d%d",&n,&x);
    for(int i=0;i<=n;i++) scanf("%d",&a[i]);
    for (int i=n;i>=0;i--)
    ans=ans*x+a[i];
    printf("%lld",ans);
}

单调队列
给定一个长度为N的整数数列a(i),i=0,1,…,N-1和窗长度k.

要求:

f(i)=max(a(ik+1),a(ik+2),...,a(i))i=1,2,3,..n

#include<bits/stdc++.h>
using namespace std;
int x,n,k,head=1,tail;
struct os
{
    int data,num;
}q[500000];
main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if (head<=tail&&i-q[head].num>=k) head++;
        while (head<=tail)
        {
            if (q[tail].data>x) break;
            tail--;
        }
        q[++tail].data=x;
        q[tail].num=i;
        if (i>=k) printf("%d ",q[head].data);
    }
}

邻接表+堆优化dijskra求最短路
点对中的优先级比较first>second,所以把dis当成first

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int tot,n,m;
int first[10010],dis[10010];
bool flag[10010];
struct os
{
    int w,u,v,next;
}e[200010];
void add(int x,int y,int z)
{
    e[++tot].u=x;
    e[tot].v=y;
    e[tot].w=z;
    e[tot].next=first[x];
    first[x]=tot;
}
typedef pair<int,int> xy;
priority_queue<xy,vector<xy>,greater<xy> >q; 
main()
{
    scanf("%d%d",&n,&m);
    int x,y,z;
    for (int i=1;i<=m;i++)
    scanf("%d%d%d",&x,&y,&z),
    add(x,y,z),add(y,x,z);//无向图
    memset(dis,63,sizeof(dis));
    dis[1]=0;
    q.push(make_pair(dis[1],1));
    while (!q.empty())
    {
        xy now=q.top();
        q.pop();
        if (flag[now.second]) continue;
        flag[now.second]=1;
        for (int i=first[now.second];i;i=e[i].next)
        if (dis[now.second]+e[i].w<dis[e[i].v])
        {
            dis[e[i].v]=dis[now.second]+e[i].w;
            if (!flag[e[i].v]) q.push(make_pair(dis[e[i].v],e[i].v));
        }
    }
    printf("%d",dis[n]);
}

kmp算法(求ch在s中第一次出现的位置)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
char s[100002],ch[102];
int l,next[102];
main()
{
    scanf("%s%s",s,ch);
    for (int i=1;i<strlen(ch);i++)
    {
        int k=i;
        while (ch[i]!=ch[next[k]]&&next[k]) k=next[k];
        next[i+1]=next[k]+(ch[i]==ch[next[k]]);
    }
    int now=0;
    for (int i=0;i<strlen(s);i++)
    {
        while (ch[now]!=s[i]&&now) now=next[now];
        now+=(ch[now]==s[i]);
        if (now==strlen(ch)) {printf("%d\n",i-now+1);break;}
    }
}

AC自动机:AC自动机练习
LCT:弹飞绵羊
莫队:小Z的袜子
Splay(这个特别丑,可以看别的题解):普通平衡树
背包:背包小例题
欧拉筛求φ,μ,d

#include<cstdio>
using namespace std;
int n,prime[1000010];
bool flag[1000010];
int t[1000010],d[1000010],mu[1000010],phi[1000010];
main()
{
    scanf("%d",&n);
    mu[1]=1;d[1]=1;
    for (int i=2;i<=n;i++)
    {
        if (!flag[i])
            prime[++prime[0]]=i,
            mu[i]=-1,
            phi[i]=i-1,
            t[i]=i,
            d[i]=2;
        for (int j=1;j<=prime[0];j++)
        {
            if (i*prime[j]>n) break;
            flag[prime[j]*i]=1;
            if (i%prime[j])
            {
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
                mu[i*prime[j]]=-mu[i];
                t[i*prime[j]]=1;
                d[i*prime[j]]=d[i]<<1;
            }
            else
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                mu[i*prime[j]]=0;
                t[i*prime[j]]=t[i]+1;
                d[i*prime[j]]=d[i]/(t[i]+1)*(t[i]+2);
                break;
            }
        }
    }

}

O(n)求1-n的逆元(mod为质数)
证明

#include<cstdio>
using namespace std;
int n,mod,inv[100000];
main()
{
    scanf("%d%d",&n,&mod);
    inv[1]=1;
    printf("1 ");
    for (int i=2;i<=n;i++)
    inv[i]=(mod-mod/i)*inv[mod%i]%mod,
    printf("%d ",inv[i]);
}

匈牙利

bool find(int x)
{
    for (int i=first[x];i;i=e[i].next
        if (!vis[e[i].v])
        {
            vis[e[i].v]=1;
            if (!belong[e[i].v]||find(belong[e[i].v]))
            {
                belong[e[i].v]=x;
                return 1;
            }
        }
    return 0;
}

tarjan
定义:

int low[],dfn[],cnt,first[];
bool vis[];
stack<int>s
struct edge{int v,next;}

操作:

void dfs(int x)
{
    low[x]=dfn[x]=++cnt;
    vis[x]=1;s.push(x);
    for (int i=first[x];i;i=e[i].next)
        if (!dfn[e[i].v])
            dfs(e[i].v),
            low[x]=min(low[x],low[e[i].v]);
        else if (vis[e[i].v])
            low[x]=min(low[x],dfn[e[i].v];
    if (dfn[x]==low[x])
        for (int y=-1;y!=x;y=s.top(),s.pop())
            vis[s.top()]=1,
            //...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值