模板庫

模板庫

## 圖論

SPFA

#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define X 2000007
using namespace std;
struct Edge {
    int pre,to,w;
} edge[X];
queue<int>car;
int dis[X],num_edge,head[X];
bool if_q[X];

void add(int from,int to,int w) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    edge[num_edge].w=w;
    head[from]=num_edge;
}
void spfa(int s) {
    car.push(s);
    int u,v;
    if_q[s]=1,dis[s]=0;
    while(!car.empty()) {
        u=car.front(),if_q[u]=0;
        for(int i=head[u]; i; i=edge[i].pre) {
            v=edge[i].to;
            if(edge[i].w+dis[u]<dis[v]) {
                dis[v]=dis[u]+edge[i].w;
                if(!if_q[v]) {
                    car.push(v);
                    if_q[v]=1;
                }
            }
        }
        car.pop();
    }
}
int main() {
    int n,m,u,v,w,S;
    cin>>n>>m>>S;
    for(int i=1; i<=n; ++i)
        dis[i]=2147483647;
    for(int i=1; i<=m; ++i) {
        cin>>u>>v>>w;
        add(u,v,w);
    }
    spfa(S);
    for(int i=1; i<=n; ++i)
        cout<<dis[i]<<" ";
    return 0;
}

堆優化的Dijkstra

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 200007
#define ll long long
using namespace std;
int head[X],num_edge;
ll dis[X];
bool vis[X];
struct Edge {
    int pre,to,w;
} edge[V];
struct Node {
    int u;
    ll diss;
    bool operator<(const Node &B)const {
        return diss>B.diss;
    }
};
priority_queue<Node>car;

void add(int from,int to,int w) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    edge[num_edge].w=w;
    head[from]=num_edge;
}
void dijkstra(int S) {
    Node now,nex;
    memset(dis,0x7f,sizeof(dis));
    dis[S]=0;
    now.diss=0,now.u=S;
    car.push(now);
    while(!car.empty()) {
        now=car.top(),car.pop();
        if(vis[now.u]) continue;
        vis[now.u]=1;
        for(int i=head[now.u]; i; i=edge[i].pre)
            if(dis[edge[i].to]>dis[now.u]+edge[i].w) {
                dis[edge[i].to]=dis[now.u]+edge[i].w;
                if(!vis[edge[i].to]) {
                    nex.u=edge[i].to,nex.diss=dis[edge[i].to];
                    car.push(nex);
                }
            }
    }
}
int main() {
    int S,n,m,u,v,w;
    scanf("%d%d%d",&n,&m,&S);
    for(int i=1; i<=m; ++i) {
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }

    dijkstra(S);

    for(int i=1; i<=n; ++i)
        printf("%lld ",dis[i]);
    return 0;
}

Floyed

//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 107
using namespace std;
int dis[X][X];

int main() {
    int n;
    scanf("%d",&n);
    memset(dis,0x3f,sizeof(dis));
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n; ++j)
            scanf("%d",&dis[i][j]);

    for(int k=1; k<=n; ++k)
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                if(dis[i][k]+dis[k][j]<dis[i][j])
                    dis[i][j]=dis[i][k]+dis[k][j];

    return 0;
}

Kruskal

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,fa[100007],num_edge,ans;
struct Edge {
    int from,to,w;
} edge[100007];

bool cmp(Edge x,Edge y) {
    return x.w<y.w;
}
int find(int x) {
    if(fa[x]!=x) return fa[x]=find(fa[x]);
    return fa[x];
}
int uni(int x,int y) {
    x=find(x),y=find(y);
    if(x!=y) fa[y]=x;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i)
        fa[i]=i;
    for(int i=1; i<=m; ++i)
        scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].w);

    sort(edge+1,edge+1+m,cmp);
    int u,v,t=0;
    for(int i=1; i<=m; ++i) {
        u=edge[i].from,v=edge[i].to;
        if(find(u)!=find(v)) {
            uni(u,v);
            ans=max(ans,edge[i].w);
            ++t;
            if(t==n) break;
        }
    }

    printf("%d %d",t,ans);
    return 0;
}

最小費用最大流

#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 1000007
using namespace std;
int head[V],car[X],dis[X],vio[X],reaflow[X];
int num_edge,n,m,Cost,Flow,h,t,S,T;
bool inq[X];
struct Edge {
    int pre,from,to,c,w;
} edge[V];

void add(int from,int to,int c,int w) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].from=from;
    edge[num_edge].to=to;
    edge[num_edge].c=c;
    edge[num_edge].w=w;
    head[from]=num_edge;
}
bool spfa() {
    int now,tmp;
    memset(dis,0x7f,sizeof(dis));
    memset(reaflow,0x7f,sizeof(reaflow));
    h=t=1,inq[S]=1,car[t++]=S,tmp=dis[0],dis[S]=0;
    while(h<t) {
        now=car[h++],inq[now]=0;
        for(int i=head[now]; i; i=edge[i].pre) {
            if(dis[now]+edge[i].w<dis[edge[i].to]&&edge[i].c>0) {
                dis[edge[i].to]=edge[i].w+dis[now];
                vio[edge[i].to]=i;
                reaflow[edge[i].to]=min(reaflow[now],edge[i].c);
                if(!inq[edge[i].to]) {
                    car[t++]=edge[i].to;
                    inq[edge[i].to]=1;
                }
            }
        }
    }
    if(dis[T]==tmp) return 0;
    return 1;
}
int main() {
    int u,v,c,w;
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for(int i=1; i<=m; ++i) {
        scanf("%d%d%d%d",&u,&v,&c,&w);
        add(u,v,c,w);
    }
    while(spfa()) {
        Cost+=dis[T]*reaflow[T];
        Flow+=reaflow[T];
        for(int i=vio[T]; i; i=vio[edge[i].from]) {
            edge[i].c-=reaflow[T];
            add(edge[i].to,edge[i].from,reaflow[T],-edge[i].w);
        }
    }
    printf("%d %d",Flow,Cost);
    return 0;
}

求樹的重心

//... ...
#include<cstdio>
#include<iostream>
#include<cstring>
#define INF 0x7fffffff
#define X 20007
using namespace std;
struct Edge {
    int pre,to;
} edge[X<<1];
int head[X],siz[X],maxs[X],n,num_edge,num_node,ans;
//siz[i]爲以i爲根的子樹大小,maxs[i]爲刪去i後最大子樹大小

void add(int from,int to) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    head[from]=num_edge;
}
void dfs(int now,int from) {
    int v;
    siz[now]++;
    for(int i=head[now]; i; i=edge[i].pre) {
        v=edge[i].to;
        if(v==from)continue;
        dfs(v,now);
        siz[now]+=siz[v];
        maxs[now]=max(maxs[now],siz[v]);
    }
    maxs[now]=max(maxs[now],n-siz[now]);
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        num_edge=0,num_node=INF;
        memset(head,0,sizeof(head));
        memset(siz,0,sizeof(siz));
        memset(maxs,0,sizeof(maxs));
        scanf("%d",&n);
        int u,v;
        for(int i=1; i<=n-1; i++) {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs(1,0);
        for(int i=1; i<=n; i++)
            if(maxs[i]<num_node)
                num_node=maxs[i],ans=i;
        printf("%d %d\n",ans,num_node);
    }
    return 0;
}

LCA tarjian版

//... ...
#include<cstdio>
#include<iostream>
#define X 500007
using namespace std;
int head[X],fa[X],has[X],ans[X];
int num_edge,num_q;
bool vis[X];
struct Edge {
    int pre,to;
} edge[X<<1];
struct Qs {
    int pre,id,v;
} qs[X<<1];

void add(int from,int to) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    head[from]=num_edge;
}
void add_Q(int u,int v,int tim) {
    qs[++num_q].pre=has[u],qs[num_q].id=tim;
    qs[num_q].v=v;
    has[u]=num_q;
}
int find(int x) {
    if(x!=fa[x]) return fa[x]=find(fa[x]);
    return x;
}
void tar(int now) {
    fa[now]=now,vis[now]=1;
    for(int i=head[now]; i; i=edge[i].pre) {
        if(!vis[edge[i].to]) {
            tar(edge[i].to);
            fa[edge[i].to]=now;
        }
    }
    for(int i=has[now]; i; i=qs[i].pre)
        if(vis[qs[i].v])
            ans[qs[i].id]=find(qs[i].v);
}
int main() {
    int n,m,s,u,v;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1; i<n; ++i) {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    for(int i=1; i<=m; ++i) {
        scanf("%d%d",&u,&v);
        add_Q(u,v,i),add_Q(v,u,i);
    }
    tar(s);
    for(int i=1; i<=m; ++i)
        printf("%d\n",ans[i]);
    return 0;
}

LCA 倍增版

#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
const int MAX=500001;
int n,m,s,head[MAX],num_node,p,fa[MAX],f[MAX][20],id[MAX],S=1;
struct Node {
    int pre,to;
} node[MAX*2];

void add(int from,int to) {
    node[++num_node].pre=head[from];
    node[num_node].to=to;
    head[from]=num_node;
}
void dfs(int x) {
    for(int i=head[x]; i; i=node[i].pre) {
        if(!id[node[i].to]) {
            id[node[i].to]=++S;
            fa[node[i].to]=x;
            dfs(node[i].to);
        }
    }
}
void pre() {
    p=int(log(n)/log(2)+0.001);
    for(int i=1; i<=n; ++i)
        if(fa[i]) f[i][0]=fa[i];
    for(int i=1; i<=p; ++i)
        for(int j=1; j<=n; ++j)
            f[j][i]=f[f[j][i-1]][i-1];
}
int ask(int x,int y) {
    if(id[x]<id[y]) swap(x,y);
    for(int i=p; i>=0; --i)
        if(id[f[x][i]]>id[y])
            x=f[x][i];
    return f[x][0];
}
int main() {
    scanf("%d%d%d",&n,&m,&s);
    int from,to;
    for(int i=1; i<=n-1; ++i) {
        scanf("%d%d",&from,&to);
        add(from,to);
        add(to,from);
    }

    id[s]=1;
    dfs(s);
    pre();
    int x,y;
    for(int i=1; i<=m; ++i) {
        scanf("%d%d",&x,&y);
        printf("%d\n",ask(x,y));
    }

    return 0;
}

Tarjian 求割點

//... ...
#include<cstdio>
#include<iostream>
#define X 100007
#define V 200007
using namespace std;
int head[X],dfn[X],low[X];
int n,m,num_edge,tot,ans=0;
bool cutnode[X];
struct Edge {
    int pre,to;
} edge[V];

void add(int from,int to) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    head[from]=num_edge;
}
void tar(int now,int fa) {
    int numson=0;
    dfn[now]=low[now]=++tot;
    for(int i=head[now]; i; i=edge[i].pre) {
        if(edge[i].to==fa) continue;
        if(!dfn[edge[i].to]) {
            ++numson;
            tar(edge[i].to,now);
            low[now]=min(low[now],low[edge[i].to]);
            if(low[edge[i].to]>=dfn[now])
                cutnode[now]=1;
        } else low[now]=min(low[now],dfn[edge[i].to]);
    }
    if(!fa&&numson<2) cutnode[now]=0;
    if(cutnode[now]) ++ans;
}
int main() {
    int u,v;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i) {
        scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }

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

    printf("%d\n",ans);
    for(int i=1; i<=n; ++i)
        if(cutnode[i]) printf("%d ",i);
    return 0;
}

Tarjian 縮點

//... ...
#include<cstdio>
#include<iostream>
#define X 10007
#define V 50007
using namespace std;
int dfn[X],low[X],siz[X],bel[X],stack[X],outdu[X],lik[X];
int tot,cnt;
struct Graph {
    int num_edge,head[X];
    struct Edge {
        int pre,to;
    } edge[V];
    void add(int from,int to) {
        edge[++num_edge].pre=head[from];
        edge[num_edge].to=to;
        head[from]=num_edge;
    }
} G1;

void tar(int now) {
    dfn[now]=low[now]=++cnt,stack[++stack[0]]=now;
    for(int i=G1.head[now]; i; i=G1.edge[i].pre) {
        if(!dfn[G1.edge[i].to]) {
            tar(G1.edge[i].to);
            low[now]=min(low[now],low[G1.edge[i].to]);
        } else low[now]=min(low[now],dfn[G1.edge[i].to]);
    }
    if(dfn[now]==low[now]) {
        int num=0;
        ++tot;
        while(stack[0]) {
            bel[stack[stack[0]--]]=tot,++num;
            if(stack[stack[0]+1]==now) break;
        }
        lik[tot]=siz[tot]=num;
    }
}
int main() {
    int n,m,u,v,now,ans=0,wtc;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i) {
        scanf("%d%d",&u,&v);
        G1.add(u,v);
    }
    for(int i=1; i<=n; ++i)
        if(!dfn[i]) tar(i);
    for(int i=1; i<=n; ++i)
        for(int j=G1.head[i]; j; j=G1.edge[j].pre)
            if(bel[i]!=bel[G1.edge[j].to])
                ++outdu[bel[i]];
    for(int i=1; i<=tot; ++i)
        if(!outdu[i]) ++ans,wtc=i;
    if(ans==1)
        printf("%d",siz[wtc]);
    else printf("0");
    return 0;
}

差分約束

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
#define V 10000007
#define ll long long
using namespace std;
int head[X],num_edge;
queue<int>car;
int tim[X],N,K;
ll dis[X];
bool inq[X];
struct Edge {
    int pre,to,w;
} edge[V];

void add(int from,int to,int w) {
    edge[++num_edge].pre=head[from];
    edge[num_edge].to=to;
    edge[num_edge].w=w;
    head[from]=num_edge;
}
ll SPFA() {
    for(int i=1; i<=N; ++i)
        car.push(i),dis[i]=1,inq[i]=1,tim[i]=1;
    int now;
    while(!car.empty()) {
        now=car.front(),car.pop(),inq[now]=0;
        for(int i=head[now]; i; i=edge[i].pre)
            if(dis[now]+edge[i].w>dis[edge[i].to]) {
                dis[edge[i].to]=dis[now]+edge[i].w;
                if(!inq[edge[i].to]) {
                    car.push(edge[i].to),inq[edge[i].to]=1;
                    if(++tim[edge[i].to]>=N) return -1;
                }
            }
    }
    ll sum=0;
    for(int i=1; i<=N; ++i)
        sum+=dis[i];
    return sum;
}
int main() {
    int x,u,v;
    ll ans;

    scanf("%d%d",&N,&K);

    for(int i=1; i<=K; ++i) {
        scanf("%d%d%d",&x,&u,&v);
        if(x==1)
            add(v,u,0),add(u,v,0);
        else if(x==2) {
            if(u==v) {
                printf("-1");
                return 0;
            }
            add(u,v,1);
        } else if(x==3) add(v,u,0);
        else if(x==4) {
            if(u==v) {
                printf("-1");
                return 0;
            }
            add(v,u,1);
        } else add(u,v,0);
    }
    ans=SPFA();

    cout<<ans;
    return 0;
}

二分圖帶權匹配

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 305;
const int INF = 0x3f3f3f3f;

int love[MAXN][MAXN];
int ex_girl[MAXN],ex_boy[MAXN];
bool vis_girl[MAXN],vis_boy[MAXN];
int match[MAXN],slack[MAXN];
int N;

bool dfs(int girl) {
    vis_girl[girl] = true;
    for (int boy = 0; boy < N; ++boy) {
        if (vis_boy[boy]) continue;
        int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
        if (gap == 0) {
            vis_boy[boy] = true;
            if (match[boy] == -1 || dfs( match[boy] )) {
                match[boy] = girl;
                return true;
            }
        } else {
            slack[boy] = min(slack[boy], gap);
        }
    }
    return false;
}
int KM() {
    memset(match, -1, sizeof match);
    memset(ex_boy, 0, sizeof ex_boy);
    for (int i = 0; i < N; ++i) {
        ex_girl[i] = love[i][0];
        for (int j = 1; j < N; ++j) {
            ex_girl[i] = max(ex_girl[i], love[i][j]);
        }
    }
    for (int i = 0; i < N; ++i) {

        fill(slack, slack + N, INF);

        while (1) {
            memset(vis_girl, false, sizeof vis_girl);
            memset(vis_boy, false, sizeof vis_boy);
            if (dfs(i)) break;
            int d = INF;
            for (int j = 0; j < N; ++j)
                if (!vis_boy[j]) d = min(d, slack[j]);
            for (int j = 0; j < N; ++j) {
                if (vis_girl[j]) ex_girl[j] -= d;
                if (vis_boy[j]) ex_boy[j] += d;
                else slack[j] -= d;
            }
        }
    }
    int res = 0;
    for (int i = 0; i < N; ++i)
        res += love[ match[i] ][i];
    return res;
}
int main() {
    while (~scanf("%d", &N)) {
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < N; ++j)
                scanf("%d", &love[i][j]);
        printf("%d\n", KM());
    }
    return 0;
}

## 數學

GCD

int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}

同餘方程 (含擴歐)

#include<iostream>
using namespace std;

int extend_gcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;y=0;
        return a;
    }
    else {
        int r=extend_gcd(b,a%b,x,y);
        int t=x-a/b*y;
        x=y;y=t;
        return r;
    }
}
int main(){
    int a,b,x,y;
    cin>>a>>b;
    extend_gcd(a,b,x,y);
    while(x<0) 
        x=x+b;
    cout<<x;
    return 0;
}

最小公倍數

\(LCM(a,b)=\frac{a*b}{gcd(a,b)}\) .
\(a_i=\prod_{j=1} prime_j^{xi}\) .
\(LCM(a_i)=\prod_{j=1}prime_j^{max(xi)},i\in[1,n]\) .ios


線性篩素數

void sieve(int x) {
    memset(isPrime,1,sizeof(isPrime));
    isPrime[0]=isPrime[1]=0;
    for(int i=2; i<=x; ++i) {
        if(isPrime[i]) prime[++tot]=i;
        for(int j=1; j<=tot&&i*prime[j]<=x; ++j) {
            isPrime[i*prime[j]]=0;
            if(i%prime[j]==0) break;
        }
    }
}

篩歐拉函數\(\phi(x)\)

phi[1]=1;
for(int i=2; i<=N; i++) {
    if(!mark[i]) prime[++tot]=i,phi[i]=i-1;
    for(int j=1; j<=tot&&i*prime[j]<=N; j++) {
        mark[i*prime[j]]=1;
        if(i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
        //歐拉函數是積性函數,phi[i*prime[j]]=phi[i]*phi[prime[j]].
        //而因爲prime[j]是素數,因此phi[prime[j]]=prime[j]-1;
        else {
            phi[i*prime[j]]=phi[i]*prime[j];
            break;
        }
    }
}

線性求逆元

\(A_i=(p-p/i)*A_{p\%i}\%p\)數組


費馬小定理求逆元

\(a^{-1}=a^{p-2}(\mod p),p\)爲質數.數據結構


歐拉定理

\(n,a\)爲正整數,且\(n,a\)互質,則
\(a^{-1}=a^{\phi(p)-1}(mod\ p)\).函數


組合數遞推式

\(C[i][0]=1\)
\(C(n,m)=C(n-1,m-1)+C(n,m-1)\)測試


高斯消元

//... ...
#include<cmath>
#include<cstdio>
#include<iostream>
#define X 107
using namespace std;
double a[X][X],x[X];
int n;
double del;

bool guass() {
    for(int i=1; i<=n; ++i) {
        int p=i;
        for(int j=i+1; j<=n; ++j)
            if(fabs(a[j][i])>fabs(a[p][i]))
                p=j;
        if(fabs(a[p][i])<1e-8) return 0;
        if(p!=i)
            for(int j=i; j<=n+1; ++j)
                swap(a[i][j],a[p][j]);
        for(int j=i+1; j<=n; ++j) {
            del=a[i][i]/a[j][i];
            for(int k=i; k<=n+1; ++k)
                a[j][k]=a[i][k]-del*a[j][k];
        }
    }
    for(int i=n; i; --i) {
        for(int j=n; j>i; --j)
            a[i][n+1]-=a[i][j]*x[j];
        x[i]=a[i][n+1]/a[i][i];
    }
    return 1;
}
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; ++i)
        for(int j=1; j<=n+1; ++j)
            scanf("%lf",&a[i][j]);

    if(guass())
        for(int i=1; i<=n; ++i)
            printf("%.2lf\n",x[i]);
    else printf("No Solution");

    return 0;
}

錯位排列

若是一個\(n\)的全排列知足\(\forall a_i\neq i\),
則稱它是一個錯位排列.方案數\(D(n)=(n-1)(D(n-1)+D(n-2)))\) .優化


中國剩餘定理 CRT

#include<cstdio>
#include<iostream>
#define X 17
#define ll long long
using namespace std;
ll a[X],m[X],SM,d;

ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x=1,y=0;
        return a;
    }
    ll ret=exgcd(b,a%b,x,y);
    ll tmp=x;
    x=y,y=tmp-a/b*y;
    return ret;
}
ll CRT(){
    ll x,y,ans=0,Mi;
    for(ll i=1;i<=3;++i){
        Mi=SM/m[i];
        exgcd(Mi,m[i],x,y);
        ans+=Mi*x*a[i];
    }
    while(ans>d) ans-=SM;
    while(ans<=d) ans+=SM;
    
    return ans-d;
}
int main(){
    int tot=0;
    m[1]=23,m[2]=28,m[3]=33,SM=21252;
    while(scanf("%lld%lld%lld%lld",&a[1],&a[2],&a[3],&d)){
        ++tot;
        if(a[1]==-1) break;
        printf("Case %d: the next triple peak occurs in %lld days.\n",tot,CRT());
    }
    return 0;
}

Lucas 定理

//... ...
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
ll p;

ll ksm(ll n,ll m) {
    ll ans=1,now=n;
    while(m) {
        if(m&1) ans=(ans*now)%p;
        now=(now*now)%p,m>>=1;
    }
    return ans%p;
}
ll cm(ll n,ll m) {
    if(n<m) return 0;
    if(m>n-m) m=n-m;
    long long s1=1,s2=1;
    for(ll i=0; i<m; ++i)
        s1=s1*(n-i)%p,s2=s2*(i+1)%p;
    return s1*ksm(s2,p-2)%p;
}
ll Lucas(ll n,ll m) {
    if(!m) return 1;
    return cm(n%p,m%p)*Lucas(n/p,m/p)%p;
}
int main() {
    ll n,m,T;
    scanf("%lld",&T);
    while(T--) {
        scanf("%lld%lld%lld",&n,&m,&p);
        printf("%lld\n",Lucas(n+m,m));
    }
    return 0;
}

Miller-Rabin 素性測試

#include<cstdio>
#include<iostream>
using namespace std;
int prime[]={0,2,3,5,7,11};

long long ksm(int n,int m,int mod){
    int ans=1,now=n;
    while(m){
        if(m&1) ans*=now,ans%=mod;
        now*=now,now%=mod,m>>=1;
    }
    return ans;
}
bool Miller_Rabin(int a,int x){
    int s=0,d=x-1;
    while(d&&(!(d&1))) ++s,d>>=1;
    long long k=ksm(a,d,x);
    if(k==1||k==x-1) return 1;
    for(int i=1;i<=s;++i){
        k=k*k%x;
        if(k==x-1) return 1;
    }
    return 0;
}
bool Judge(int x){
    if(x==1) return 0;
    for(int i=1;i<=5;++i){
        if(x==prime[i]) return 1;
        if(!(x%prime[i])) return 0;
        if(!Miller_Rabin(prime[i],x)) return 0;
    }
    return 1;
}
int main(){
    int T,l,r;
    cin>>T;
    while(T--){
        cin>>l>>r;
        for(int i=l;i<=r;++i)
            if(Judge(i)) printf("%d\n",i);
        printf("\n");
    }
    return 0;
}

快速乘與快速冪

//... ...快速乘與快速冪(可帶%)
#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
ll ksc(ll n,ll m) {
    ll ans=0,now=n,f=1;  //f是用來存負號的
    if(now<0) f=-1,now=-now;
    if(m<0) f=-f,m=-m;
    while(m) {
        if(m&1) ans+=now;
        now+=now,m>>=1;
    }
    return ans*f;
}
ll ksm(ll n,ll m) {
    int ans=1,now=n;
    while(m) {
        if(m&1) ans*=now;
        now*=now,m>>=1;
    }
    return ans;
}
int main() {

    return 0;
}

篩莫比烏斯函數

//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 100007
using namespace std;
int mu[X],prime[X],tot;
bool is_Prime[X];

void sieve(int x) {
    mu[1]=1;
    memset(is_Prime,1,sizeof(is_Prime));
    is_Prime[0]=is_Prime[1]=0;
    for(int i=2; i<=x; i++) {
        if(is_Prime[i]) {
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(int j=1; prime[j]*i<=x; j++) {
            is_Prime[prime[j]*i]=0;
            if(i%prime[j]==0) {
                mu[prime[j]*i]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
}

int main() {
    int n;
    scanf("%d",&n);
    sieve(n);
    return 0;
}

## 數據結構

Splayui

//... ...
#include<cstdio>
#include<iostream>
#define X 100007
using namespace std;
int root,kep,n,tot;
int fa[X],data[X],ch[X][2],siz[X],cnt[X];

void pushup(int rt) {
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=siz[l]+siz[r]+cnt[rt];
}
void rotate(int x,int &k) {
    int a=fa[x],b=fa[a],l,r;
    l= (ch[a][0]!=x);
    r= l^1;
    if(a==k) k=x;
    else
        ch[b][ch[b][1]==a]=x;
    fa[x]=b,fa[a]=x,fa[ch[x][r]]=a;
    ch[a][l]=ch[x][r],ch[x][r]=a;
    pushup(a);
}
void splay(int x,int &k) {
    int a,b;
    while(x!=k) {
        a=fa[x],b=fa[a];
        if(a!=k) {
            if((ch[a][0]==x)^(ch[b][0]==a))
                rotate(x,k);
            else
                rotate(a,k);
        }
        rotate(x,k);
        pushup(x);
    }
}
void ins(int &rt,int x) {
    if(rt==0) {
        rt=++kep;
        data[kep]=x;
        siz[kep]=cnt[kep]=1;
        return;
    }
    if(x==data[rt]) {
        cnt[rt]++;
        siz[rt]++;
        return;
    }
    if(x<data[rt]) {
        ins(ch[rt][0],x);
        fa[ch[rt][0]]=rt;
        pushup(rt);
    } else {
        ins(ch[rt][1],x);
        fa[ch[rt][1]]=rt;
        pushup(rt);
    }
}
int getmn(int rt) {
    while(ch[rt][0]) {
        rt=ch[rt][0];
    }
    if(!rt) return -1;
    return rt;
}
void del(int rt,int x) {
    if(data[rt]==x) {
        if(cnt[rt]>1) {
            cnt[rt]--;
            siz[rt]--;
        } else {
            splay(rt,root);
            int p=getmn(ch[rt][1]);
            if(p!=-1) {
                splay(p,root);
                fa[p]=0;
                ch[p][0]=ch[rt][0];
                fa[ch[rt][0]]=p;
                pushup(p);
            } else {
                root=ch[rt][0];
                fa[ch[rt][0]]=0;
            }
        }
        return;
    }
    if(x<data[rt]) {
        del(ch[rt][0],x);
        pushup(rt);
    } else {
        del(ch[rt][1],x);
        pushup(rt);
    }
}
int getpre(int rt,int x) {
    int p=rt,ans;
    while(p) {
        if(x<=data[p]) {
            p=ch[p][0];
        } else {
            ans=p;
            p=ch[p][1];
        }
    }
    return ans;
}
int getsuc(int rt,int x) {
    int p=rt,ans;
    while(p) {
        if(x>=data[p]) {
            p=ch[p][1];
        } else {
            ans=p;
            p=ch[p][0];
        }
    }
    return ans;
}
int geth(int rt,int k) {
    if(data[rt]==k) {
        splay(rt,root);
        if(ch[rt][0]==0) {
            return 1;
        } else {
            return siz[ch[rt][0]]+1;
        }
    }
    if(k<data[rt]) return geth(ch[rt][0],k);
    else return geth(ch[rt][1],k);
}
int getkth(int rt,int k) {
    int l=ch[rt][0];
    if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return data[rt];
    if(k<siz[l]+1) return getkth(ch[rt][0],k);
    if(siz[l]+cnt[rt]<k) return getkth(ch[rt][1],k-(siz[l]+cnt[rt]));
}
int main() {
    int opt,x;
    scanf("%d",&n);
    while(n--) {
        scanf("%d%d",&opt,&x);
        if(opt==1) {
            tot++;
            ins(root,x);
        }
        if(opt==2) {
            tot--;
            del(root,x);
        }
        if(opt==3) {
            printf("%d\n",geth(root,x));
        }
        if(opt==4) {
            printf("%d\n",getkth(root,x));
        }
        if(opt==5) {
            printf("%d\n",data[getpre(root,x)]);
        }
        if(opt==6) {
            printf("%d\n",data[getsuc(root,x)]);
        }
    }
    return 0;
}

線段樹

#include<cstdio>
#include<iostream>
#define X 100005
using namespace std;
long long askl,askr,ans,add;
struct Tree {
    long long l,r,w,f;
} tree[X<<2];

void pushdown(long long k) {
    tree[k<<1].f+=tree[k].f;
    tree[k<<1|1].f+=tree[k].f;
    tree[k<<1].w+=tree[k].f*(tree[k<<1].r-tree[k<<1].l+1);
    tree[k<<1|1].w+=tree[k].f*(tree[k<<1|1].r-tree[k<<1|1].l+1);
    tree[k].f=0;
}
void build(long long k,long long l,long long r) {
    tree[k].l=l,tree[k].r=r;
    if(tree[k].l==tree[k].r) {
        scanf("%lld",&tree[k].w);
        return ;
    }
    long long mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
}
void change_nevl(long long k) {
    if(askl<=tree[k].l&&tree[k].r<=askr) {
        tree[k].f+=add;
        tree[k].w+=add*(tree[k].r-tree[k].l+1);
        return ;
    }
    if(tree[k].f) pushdown(k);
    long long mid=(tree[k].l+tree[k].r)>>1;
    if(askl<=mid) change_nevl(k<<1);
    if(askr>mid) change_nevl(k<<1|1);
    tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
}
void ask_nevl(long long k) {
    if(askl<=tree[k].l&&tree[k].r<=askr) {
        ans+=tree[k].w;
        return;
    }
    if(tree[k].f) pushdown(k);
    long long mid=(tree[k].l+tree[k].r)>>1;
    if(askl<=mid) ask_nevl(k<<1);
    if(askr>mid) ask_nevl(k<<1|1);
}
int main() {
    long long n,m,t;
    cin>>n>>m;
    build(1,1,n);
    while(m--) {
        cin>>t;
        if(t==1) {
            cin>>askl>>askr>>add;
            change_nevl(1);
        } else {
            cin>>askl>>askr;
            ans=0;
            ask_nevl(1);
            cout<<ans<<endl;
        }
    }
    return 0;
}

樹狀數組

#include<cstdio>
#include<iostream>
#define X 500007
using namespace std;
int n,m,c[X];

inline int lowbit(int x) {
    return x&(-x);
}
void add(int p,int x) {
    while(p<=n)
        c[p]+=x,p+=lowbit(p);
}
int getnevl(int r) {
    int ans=0;
    while(r)
        ans+=c[r],r-=lowbit(r);
    return ans;
}
int main() {
    int x,a,c;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) {
        scanf("%d",&x);
        add(i,x);
    }
    while(m--) {
        scanf("%d%d%d",&a,&x,&c);
        if(a==1)
            add(x,c);
        else printf("%d\n",getnevl(c)-getnevl(x-1));
    }
    return 0;
}

替罪羊樹

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define INF (1<<30)
#define X (2100000)
#define al (0.75)
using namespace std;
struct node {
    int son[2],fa,size,num;
} t[X];
int n,cnt,root,cur[X],sum;

bool balance(int x) { //平衡限制,這裏的 alpha 取0.75
    return (double)t[x].size*al>=(double)t[t[x].son[0]].size
           && (double) t[x].size*al>=(double)t[t[x].son[1]].size;
}
void recycle(int id) {  //壓扁成一個序列,按大小順序回收節點
    if(t[id].son[0]) recycle(t[id].son[0]);
    cur[++sum]=id;
    if(t[id].son[1]) recycle(t[id].son[1]);
}
int build(int l,int r) { //遞歸建樹
    if(l>r) return 0;
    int mid=(l+r)>>1,id=cur[mid];
    t[id].son[0]=build(l,mid-1),t[t[id].son[0]].fa=id;
    t[id].son[1]=build(mid+1,r),t[t[id].son[1]].fa=id;
    t[id].size=t[t[id].son[0]].size+t[t[id].son[1]].size+1;
    return id;
}
void rebuild(int id) { //重構
    sum=0;
    recycle(id);
    int fa=t[id].fa,Son=(t[t[id].fa].son[1]==id);
    int cur=build(1,sum);
    t[fa].son[Son]=cur,t[cur].fa=fa;
    if(id==root) root=cur;
}
void ins(int x) {
    int now=root,cur=++cnt;
    t[cur].size=1,t[cur].num=x;
    while(1) { //插入維護序列,左小右大
        t[now].size++;
        bool Son=(x>=t[now].num);
        if( t[now].son[Son] ) now=t[now].son[Son];
        else {
            t[now].son[Son]=cur,t[cur].fa=now;
            break;
        }
    }
    int flag=0;
    for(int i=cur; i; i=t[i].fa) if(!balance(i)) flag=i;
    if(flag) rebuild(flag); //插入每每會致使不平衡,這時只須要重建不平衡的子樹便可
}
int get_num(int x) { //查詢 x 在樹中的節點編號
    int now=root;
    while(1) {
        if(t[now].num==x) return now;
        else now=t[now].son[x>t[now].num];
    }
}
void del(int id) { //刪除
    if(t[id].son[0] && t[id].son[1]) {
        int cur=t[id].son[0];
        while(t[cur].son[1]) cur=t[cur].son[1];
        t[id].num=t[cur].num;
        id=cur;
    }  //刪除操做須要找到左子樹的最後一個節點或右子樹的第一個節點來頂替,優先找左子樹
    int Son=(t[id].son[0]) ? t[id].son[0]:t[id].son[1];
    int k=(t[t[id].fa].son[1]==id );
    t[t[id].fa].son[k]=Son,t[Son].fa=t[id].fa;
    for(int i=t[id].fa; i; i=t[i].fa) t[i].size--;
    if(id==root) root=Son;
}
int getk(int x) { //查 x 的排名
    int now=root,ans=0;
    while(now) {
        if(t[now].num<x) ans+=t[t[now].son[0]].size+1,now=t[now].son[1];
        else now=t[now].son[0];
    }
    return ans;
}
int getkth(int x) { //查樹中的第 k 個數
    int now=root;
    while(1) {
        if(t[t[now].son[0]].size==x-1) return now;
        else if(t[t[now].son[0]].size>=x) now=t[now].son[0];
        else x-=t[t[now].son[0]].size+1,now=t[now].son[1];
    }
    return now;
}
int getpre(int x) { //找前驅,即左子樹最後一個點
    int now=root,ans=-INF;
    while(now) {
        if(t[now].num<x) ans=max(ans,t[now].num),now=t[now].son[1];
        else now=t[now].son[0];
    }
    return ans;
}
int getsuc(int x) { //找後繼,即右子樹第一個點
    int now=root,ans=INF;
    while(now) {
        if(t[now].num>x) ans=min(ans,t[now].num),now=t[now].son[0];
        else now=t[now].son[1];
    }
    return ans;
}
int main() {
    cnt=2,root=1;
    t[1].num=-INF,t[1].size=2,t[1].son[1]=2;
    t[2].num=INF,t[2].size=1,t[2].fa=1;
    scanf("%d",&n);
    int opt,x;
    for(int i=1; i<=n; i++) {
        scanf("%d%d",&opt,&x);
        if(opt==1) ins(x);
        if(opt==2) del( get_num(x) );
        if(opt==3) printf("%d\n",getk(x));
        if(opt==4) printf("%d\n",t[ getkth(x+1) ].num);
        if(opt==5) printf("%d\n",getpre(x));
        if(opt==6) printf("%d\n",getsuc(x));
    }
    return 0;
}

笛卡爾樹

//... ...cogs2421
#include<cstdio>
#include<algorithm>
#define MAXN 500010
using namespace std;
struct Tree {
    int key,th;
    Tree *ch[2];
}*car[MAXN],node[MAXN],*root;
int top,n;

int cmp(const Tree a,const Tree b) {
    return a.key<b.key;
}
inline void built() {
    car[++top]=node+1;
    for(int i=2; i<=n; i++) {
        Tree *last=NULL;
        while(top&&car[top]->th>node[i].th)
            last=car[top--];
        if(top) car[top]->ch[1]=node+i;
        node[i].ch[0]=last;
        car[++top]=node+i;
    }
    root=car[1];
}
void dfs(Tree *rt) {
    if(!rt)return;
    printf("%d ",rt->key);
    dfs(rt->ch[0]);
    dfs(rt->ch[1]);
}
int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&node[i].key);
    for(int i=1; i<=n; i++) scanf("%d",&node[i].th);
    sort(node+1,node+n+1,cmp);
    built();
    dfs(root);
    return 0;
}

主席樹

//... ...
#include<cstdio>
#include<iostream>
#include<algorithm>
#define X 200007
using namespace std;
int cnt,n,ref[X],a[X],son[X*18][2],sum[X*18],root[X],tot;

void discrete() {
    sort(ref+1,ref+1+n);
    cnt=1;
    for(int i=2; i<=n; ++i)
        if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
    for(int i=1; i<=n; ++i) a[i]=lower_bound(ref+1,ref+1+cnt,a[i])-ref;
}
void built(int x,int &y,int l,int r,int pos) {
    sum[y=++tot]=sum[x]+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(pos<=mid) son[y][1]=son[x][1],built(son[x][0],son[y][0],l,mid,pos);
    else son[y][0]=son[x][0],built(son[x][1],son[y][1],mid+1,r,pos);
}
int find_pos(int x,int y,int l,int r,int k) {
    if(l==r) return l;
    int mid=l+r>>1,tmp=sum[son[y][0]]-sum[son[x][0]];
    if(k<=tmp) return find_pos(son[x][0],son[y][0],l,mid,k);
    else return find_pos(son[x][1],son[y][1],mid+1,r,k-tmp);
}
int main() {
    int m,l,r,k;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) {
        scanf("%d",&a[i]);
        ref[i]=a[i];
    }
    discrete();
    for(int i=1; i<=n; ++i)
        built(root[i-1],root[i],1,cnt,a[i]);
    while(m--) {
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",ref[find_pos(root[l-1],root[r],1,cnt,k)]);
    }
    return 0;
}

ST表

//... ...
#include<cstdio>
#include<iostream>
#define X 100007
using namespace std;
int n,f_max[X][27],a[X],lg2[X];

void pre() {
    lg2[0]=-1;
    for(int i=1; i<=n; ++i) {
        lg2[i]=((i&(i-1))==0)? lg2[i-1]+1:lg2[i-1];
        f_max[i][0]=a[i];
    }
    for(int i=1; i<=lg2[n]; ++i)
        for(int j=1; j+(1<<i)-1<=n; ++j)
            f_max[j][i]=max(f_max[j][i-1],f_max[j+(1<<(i-1))][i-1]);
}
inline int getmax(int l,int r) {
    int k=lg2[r-l+1];
    return max(f_max[l][k],f_max[r-(1<<k)+1][k]);
}
int main() {
    int m,l,r,ans;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
    pre();
    while(m--) {
        scanf("%d%d",&l,&r);
        ans=getmax(l,r);
        printf("%d\n",ans);
    }
    return 0;
}

高精度

//Author : ZlycerQan
#include <cstdio>
#include <iostream>
#include <vector>
#include <iomanip>
#include <cassert>
#include <algorithm>
#include <cstring>

const int Big_B = 1000000000;
const int Big_L = 9;
inline int intcmp_ (int a, int b) {
    if (a > b) return 1;
    return a < b ? -1 : 0;
}
struct Int {
#define rg register
    inline int max (int a, int b) {
        return a > b ? a : b;
    }
    inline int min (int a, int b) {
        return a < b ? a : b;
    }
    std :: vector <int> c;
    Int () {} typedef long long LL;
    Int (int x) {
        for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
    }
    Int (LL x) {
        for (; x > 0; c.push_back (x % Big_B), x /= Big_B);
    }
    inline void CrZ () {
        for (; !c.empty () && c.back () == 0; c.pop_back ());
    }
    inline Int &operator += (const Int &rhs) {
        c.resize (max (c.size (), rhs.c.size ()));
        rg int i, t = 0, S;
        for (i = 0, S = rhs.c.size (); i < S; ++ i)
            c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
        for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
            c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t);
        if (t) c.push_back (t);
        return *this;
    }
    inline Int &operator -= (const Int &rhs) {
        c.resize (max (c.size (), rhs.c.size ()));
        rg int i, t = 0, S;
        for (i = 0, S = rhs.c.size (); i < S; ++ i)
            c[i] -= rhs.c[i] + t, t = c[i] < 0, c[i] += Big_B & (-t);
        for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i)
            c[i] -= t, t = c[i] < 0, c[i] += Big_B & (-t);
        CrZ ();
        return *this;
    }
    inline Int &operator *= (const Int &rhs) {
        rg int na = c.size (), i, j, S, ai;
        c.resize (na + rhs.c.size ());
        LL t;
        for (i = na - 1; i >= 0; -- i) {
            ai = c[i], t = 0, c[i] = 0;
            for (j = 0, S = rhs.c.size (); j < S; ++ j) {
                t += c[i + j] + (LL) ai * rhs.c[j];
                c[i + j] = t % Big_B, t /= Big_B;
            }
            for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j)
                t += c[i + j], c[i + j] = t % Big_B, t /= Big_B;
            assert (t == 0);
        }
        CrZ ();
        return *this;
    }
    inline Int &operator /= (const Int &rhs) {
        return *this = div (rhs);
    }
    inline Int &operator %= (const Int &rhs) {
        return div (rhs), *this;
    }
    inline Int &shlb (int l = 1) {
        if (c.empty ()) return *this;
        c.resize (c.size () + l);
        rg int i;
        for (i = c.size () - 1; i >= l; -- i) c[i] = c[i - l];
        for (i = 0; i < l; ++ i) c[i] = 0;
        return *this;
    }
    inline Int &shrb (int l = 1) {
        for (rg int i = 0; i < c.size () - l; ++ i) c[i] = c[i + l];
        c.resize (max (c.size () - l, 0));
        return *this;
    }
    inline int Comp (const Int &rhs) const {
        if (c.size () != rhs.c.size ()) return intcmp_ (c.size (), rhs.c.size ());
        for (rg int i = c.size () - 1; i >= 0; -- i)
            if (c[i] != rhs.c[i]) return intcmp_ (c[i], rhs.c[i]);
        return 0;
    }
    inline Int div (const Int &rhs) {
        assert (!rhs.c.empty ());
        Int q, r;
        rg int i;
        if (rhs > *this) return 0;
        q.c.resize (c.size () - rhs.c.size () + 1);
        rg int _l, _r, mid;
        for (i = c.size () - 1; i > c.size () - rhs.c.size (); -- i) r.shlb (), r += c[i];
        for (i = c.size () - rhs.c.size (); i >= 0; -- i) {
            r.shlb ();
            r += c[i];
            if (r.Comp (rhs) < 0) q.c[i] = 0;
            else {
                _l = 0, _r = Big_B;
                for (; _l != _r; ) {
                    mid = _l + _r >> 1;
                    if ((rhs * mid).Comp (r) <= 0) _l = mid + 1;
                    else _r = mid;
                }
                q.c[i] = _l - 1, r -= rhs * q.c[i];
            }
        }
        q.CrZ (), *this = r;
        return q;
    }
    friend inline Int operator + (const Int &lhs, const Int &rhs) {
        Int res = lhs;
        return res += rhs;
    }
    friend inline Int operator - (const Int &lhs, const Int &rhs) {
        Int res = lhs;
        return res -= rhs;
    }
    friend inline Int operator * (const Int &lhs, const Int &rhs) {
        Int res = lhs;
        return res *= rhs;
    }
    friend inline Int operator / (const Int &lhs, const Int &rhs) {
        Int res = lhs;
        return res.div (rhs);
    }
    friend inline Int operator % (const Int &lhs, const Int &rhs) {
        Int res = lhs;
        return res.div (rhs), res;
    }
    friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs) {
        if (rhs.c.size () == 0) out << "0";
        else {
            out << rhs.c.back ();
            for (rg int i = rhs.c.size () - 2; i >= 0; -- i)
                out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i];
        }
        return out;
    }
    friend inline std :: istream &operator >> (std :: istream &in, Int &rhs) {
        static char s[10000];
        in >> s + 1;
        int Len = strlen (s + 1);
        int v = 0;
        LL r = 0, p = 1;
        for (rg int i = Len; i >= 1; -- i) {
            ++ v;
            r = r + (s[i] - '0') * p, p *= 10;
            if (v == Big_L) rhs.c.push_back (r), r = 0, v = 0, p = 1;
        }
        if (v != 0) rhs.c.push_back (r);
        return in;
    }
    friend inline bool operator < (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) < 0;
    }
    friend inline bool operator <= (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) <= 0;
    }
    friend inline bool operator > (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) > 0;
    }
    friend inline bool operator >= (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) >= 0;
    }
    friend inline bool operator == (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) == 0;
    }
    friend inline bool operator != (const Int &lhs, const Int &rhs) {
        return lhs.Comp (rhs) != 0;
    }
#undef rg
};
Int a;
int main () {

    return 0;
}

字符串

KMP

//... ...
#include<cstdio>
#include<cstring>
#include<iostream>
#define X 1000007
using namespace std;
char s[X],p[X];
int nex[X];

int main() {
    int lens,lenp,j;
    cin>>s+1>>p+1;
    lens=strlen(s+1),lenp=strlen(p+1);

    j=0;
    for(int i=2; i<=lenp; ++i) {
        while(j&&p[i]!=p[j+1]) j=nex[j];
        if(p[i]==p[j+1]) ++j;
        nex[i]=j;
    }
    j=0;
    for(int i=1; i<=lens; ++i) {
        while(j&&s[i]!=p[j+1]) j=nex[j];
        if(s[i]==p[j+1]) ++j;
        if(j==lenp){
            printf("%d\n",i-lenp+1);
            j=nex[j];
        }
    }

    for(int i=1; i<=lenp; ++i)
        printf("%d ",nex[i]);
    return 0;
}

AC自動機

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char ss[161][81],s[1001001];
int tot,bl[151*81],mp[151],trie[151*81][27],f[151*81],sum[151];
queue<int>car;

struct AhoCorasickAutomata {
    void insert(int j) {
        int rt=1,len=strlen(ss[j]),id;
        for(int i=0; i<len; ++i) {
            id=ss[j][i]-'a';
            if(!trie[rt][id]) {
                trie[rt][id]=++tot;
                bl[tot]=0;
                memset(trie[tot],0,sizeof(trie[tot]));
            }
            rt=trie[rt][id];
        }
        if(!bl[rt]) bl[rt]=j;
        mp[j]=bl[rt];
    }
    void getfail() {
        memset(f,0,sizeof(f));
        for(int i=0; i<26; ++i) trie[0][i]=1;
        int rt=1,j,now;
        car.push(1);
        while(!car.empty()) {
            now=car.front();
            car.pop();
            for(int i=0; i<26; ++i) {
                if(!trie[now][i]) continue;
                car.push(trie[now][i]);
                j=f[now];
                while(!trie[j][i]) j=f[j];
                f[trie[now][i]]=trie[j][i];
            }
        }
    }
    void find() {
        memset(sum,0,sizeof(sum));
        int rt=1,len=strlen(s),id,j;
        for(int i=0; i<len; ++i) {
            id=s[i]-'a';
            while(!trie[rt][id]) rt=f[rt];
            j=rt=trie[rt][id];
            while(j)
                ++sum[bl[j]],j=f[j];
        }
    }
} AC;
int main() {
    int n,ans;
    while(scanf("%d",&n)) {
        if(!n) return 0;
        ans=0;
        tot=1;
        memset(trie[1],0,sizeof(trie[1]));
        memset(mp,0,sizeof(mp));
        for(int i=1; i<=n; ++i) {
            scanf("%s",ss[i]);
            AC.insert(i);
        }
        AC.getfail();
        scanf("%s",s);
        AC.find();
        for(int i=1; i<=n; ++i)
            ans=max(ans,sum[i]);
        printf("%d\n",ans);
        for(int i=1; i<=n; ++i)
            if(sum[mp[i]]==ans) puts(ss[i]);
    }
}
相關文章
相關標籤/搜索