NOIPの模板总结

来源:互联网 发布:webservice java 实例 编辑:程序博客网 时间:2024/05/16 12:39

写在前面:
十分对不住看本篇博客的朋友,因为这篇博客是未完全写完的,之后会更新但是不知道是什么时候了,蒟蒻博主已经灰暗的退役了。但还是希望能做出一点微小的贡献,希望能对大家有帮助。

数论

GCD

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

EXGCD

// gcd(a, b) = a*x+b*y;LL exgcd(LL a, LL b, LL &x, LL &y) {    if(!b) { x = 1; y = 0; return a; }    LL x0, y0, d = exgcd(b, a%b, x0, y0);    x = y0; y = x0-(a/b)*y0;    return d;}

LUCAS

// C(n,m) =  C(n/p, m/p)*C(n%p, m%p) (mod p) (when 0 <= m <= n)// C(n,m) = 0 (mod p)   (when m > n)LL lucas(LL n, LL m, LL MOD) {    if(m > n) return 0;    if(n < MOD) return comb(n, m, MOD);    return lucas(n/MOD, m/MOD, MOD)*comb(n%MOD, m%MOD, MOD)%MOD;}

扩展LUCAS

逆元

// a^-1LL inv(LL a, LL MOD) {    LL x,y;    exgcd(a, MOD, x, y);    return (x%MOD+MOD)%MOD;} 
    vfac[0] = vfac[1] = 1;    for(int i = 2; i <= maxn; i++) vfac[i] = (MOD-MOD/i)*vfac[MOD%i]%MOD;

CRT

// x = a (mod m)LL crt(LL *va, LL *vm, int n) {    LL sum = 1, ans = 0;    for(int t = 0; t < n; t++) sum *= vm[t];    for(int t = 0; t < n; t++) {        LL mi = sum/vm[t], vmi = inv(mi, vm[t]);        ans += mi*vmi%sum*va[t]%sum;        if(ans >= sum) ans -= sum;    }    return ans;}

扩展CRT

排列组合

卡特兰数

inline LL catalan(LL N, LL MOD) { return comb(2*N, N, MOD)/(N+1); }

错排

// D(1) = 0, D(2) = 1// D(n) = (n-1)*(D(n-1)+D(n+2))LL D[maxn];void cuopai(int N, int MOD) {    D[1] = 0, D[2] = 1;    for(int i = 3; i <= N; i++) D[i] = (i-1)*(D[i-1]+D[i-2])%MOD;}

斯特林数

快速幂

inline LL powermod(LL a, LL b, LL MOD) {    LL ans = 1; a %= MOD;    while(b) {        if(b&1) ans = ans*a%MOD, b--;        b >>= 1; a = a*a%MOD;    }    return ans%MOD;}

矩阵快速幂

筛法

//筛法求素数 int pri[maxn]; void checkprime(int N) {    pri[1] = 1;    for(int i = 2; i <= sqrt(N); i++) if(!pri[i])        for(int j = 2; j*i <= N; j++) pri[i*j] = 1;} 

线性筛

//线性筛 bool isprime[maxn];int prime[maxn],mu[maxn],phi[maxn],tao[maxn],d[maxn],cnt_pri;void linear_sieve(int N) {    isprime[1] = mu[1] = phi[1] = tao[1] = 1; d[1] = 0;    for(int i = 2; i <= N; i++) {        if(!isprime[i]) prime[++cnt_pri] = i, mu[i] = -1, phi[i] = i-1, tao[i] = 2, d[i] = 1;        for(int t = 0; t < cnt_pri; t++) {            int j = prime[t]*i;            if(j > N) break;            isprime[j] = 1;            mu[j] = mu[prime[t]]*mu[i];            phi[j] = phi[prime[t]]*phi[i];            tao[j] = tao[i]<<1;            d[j] = 1;            if(!(i%prime[t])) { mu[j] = 0; phi[j] = prime[t]*phi[i]; tao[j] = tao[i]/(d[i]+1)*(d[i]+2); d[j] = d[i]+1; break; }        }    }}

高斯消元

线性基

图论

最短路

floyd

dijkstra

SPFA

差分约束系统

最短路径树

二分图

匈牙利

二分图染色

find union set

路径压缩

#include <cstdio>const int maxn = 1e6+5;int n,fa[maxn],siz[maxn];int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }void unionn(int x, int y) {    int fx = find(x), fy = find(y);    if(fx == fy) return ;    fa[fx] = fy;}//naiveint main () {    for(int i = 1; i <= n; i++) fa[i] = i;    return 0;} 

按秩合并

#include <cstdio>#include <cstring>#include <algorithm>const int N = 500005;template <class T> inline void read(T &x) {    int flag = 1; x = 0;    char ch = (char)getchar();    while(ch <  '0' || ch >  '9') { if(ch == '-')  flag = -1; ch = (char)getchar(); }    while(ch >= '0' && ch <= '9') { x = (x<<1)+(x<<3)+ch-'0'; ch = (char)getchar(); }    x *= flag;}int n,m,fa[N],rank[N],tim,w[N],dep[N];int Merge(int u, int v) {    if(rank[u] > rank[v]) fa[v] = u, w[v] = tim;    else {        fa[u] = v; w[u] = tim;        if(rank[u] == rank[v]) rank[v]++;    }}int Find(int x) { return fa[x] == x ? x : Find(fa[x]); }void Dfs(int u) {    if(fa[u] == u) return;    Dfs(fa[u]);    dep[u] = dep[fa[u]] + 1;}int Query(int u, int v) {    int ans = 0;    Dfs(u), Dfs(v);    if(dep[u] < dep[v]) std :: swap(u, v);    while(dep[u] > dep[v] && u != v) ans = std :: max(ans, w[u]), u = fa[u];    while(u != v) ans = std :: max(std :: max(ans, w[u]), w[v]), u = fa[u], v = fa[v];    return ans;}int main() {    read(n), read(m);    for(int i = 1; i <= n; i++) fa[i] = i;    int lsa = 0, opt, a, b;    for(int i = 1; i <= m; i++) {        read(opt), read(a), read(b);        a ^= lsa, b ^= lsa;        int tp1 = Find(a), tp2 = Find(b);        if(!opt) {            tim++;            if(tp1 != tp2) Merge(tp1, tp2);        }        else             if(tp1 != tp2) printf("0\n"), lsa = 0;            else lsa = Query(a, b), printf("%d\n",lsa);    }    return 0;}

欧拉回路

Tarjan

割点

void tarjan(int u, int fa) {    dfn[u] = low[u] = ++idc;    for(int i = head[u]; i; i = e[i].next) {        int v = e[i].v;        if(v == fa) continue;        if(!dfn[v]) {            tarjan(v, u);            low[u] = min(low[u], low[v]);            if(low[v] >= dfn[u]) iscut[u]++;        } else low[u] = min(low[u], dfn[v]);    }}

桥边

void tarjan(int u, int fa) {    dfn[u] = low[u] = ++idc;    int times = 0;    for(int i = head[u]; i; i = e[i].next) {        int v = e[i].v;        if(!dfn[v]) {            tarjan(v, u);            low[u] = min(low[u], low[v]);            if(low[v] > dfn[u]) bridge[++bridgecnt] = i;        } else if(v == fa) {            if(times) low[u] = min(low[u], dfn[v]);            times++;        } else low[u] = min(low[u], dfn[v]);    }}

缩点

#include <iostream>#include <cstdio>using namespace std;int n,m,d,cnt,scc,ind,top;int v[105],w[105],sv[105],sw[105];int dfn[105],low[105],blg[105];int q[105],f[105][505],in[505];struct edge { int to,nxt; } e[505],ed[505];int lst[105],lst2[105];bool inq[105];template <class T> inline void read(T &x) {    int flag = 1; x = 0;    char ch = (char)getchar();    while(ch <  '0' || ch >  '9') { if(ch == '-')  flag = -1; ch = (char)getchar(); }    while(ch >= '0' && ch <= '9') { x = (x<<1)+(x<<3)+ch-'0'; ch = (char)getchar(); }    x *= flag;}inline void add(int u, int v) { e[++cnt].to = v; e[cnt].nxt = lst[u]; lst[u] = cnt; }inline void ins(int u, int v) { in[v] = 1; ed[++cnt].to = v; ed[cnt].nxt = lst2[u]; lst2[u] = cnt; }void tarjan(int x) {    int now = 0;    low[x] = dfn[x] = ++ind;    q[++top] = x; inq[x] = 1;    for(int i = lst[x]; i; i = e[i].nxt)        if(!dfn[e[i].to]) tarjan(e[i].to), low[x] = min(low[x], low[e[i].to]);         else if(inq[e[i].to]) low[x] = min(low[x], dfn[e[i].to]);    if(low[x] == dfn[x]) {        scc++;        while(now != x) {            inq[now = q[top--]] = 0;            blg[now] = scc;            sv[scc] += v[now];            sw[scc] += w[now];        }    }}void dp(int x) {    for(int i = lst2[x]; i; i = ed[i].nxt) {        dp(ed[i].to);        for(int j = m-sw[x]; j >= 0; j--)            for(int k = 0; k <= j; k++) f[x][j] = max(f[x][j], f[x][k]+f[ed[i].to][j-k]);    }    for(int j = m; j >= 0; j--) f[x][j] = j >= sw[x] ? f[x][j-sw[x]]+sv[x] : 0;}int main() {    read(n); read(m);    for(int i = 1; i <= n; i++) read(w[i]);    for(int i = 1; i <= n; i++) read(v[i]);    for(int i = 1; i <= n; i++) { read(d); if(d) add(d, i); }    for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i);    cnt = 0;    for(int x = 1; x <= n; x++)        for(int i = lst[x]; i; i = e[i].nxt)            if(blg[e[i].to] != blg[x]) ins(blg[x], blg[e[i].to]);    for(int i = 1; i <= scc; i++) if(!in[i]) ins(scc+1, i);    dp(scc+1);    printf("%d\n",f[scc+1][m]);    return 0;}

MST

#include<cstdio>#include<ctime>#include<iostream>#include<algorithm>using namespace std;const int maxn = 305;int n,x,tot,ans;int fa[maxn];struct edge {    int u,v,val;    bool operator < (const edge &a) const { return val < a.val; }} e[maxn*maxn];int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }inline void unionn(int a, int b) { fa[find(a)] = find(b); }int main() {    scanf("%d",&n);    for(int i = 1; i <= n; i++) scanf("%d",&x), e[++tot].u = 0, e[tot].v = i, e[tot].val = x, fa[i] = i;    for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++)        scanf("%d",&x), e[++tot].u = i, e[tot].v = j, e[tot].val = x;    sort(e+1, e+1+tot);    for(int i = 1; i <= tot; i++) if(find(e[i].u) != find(e[i].v)) ans += e[i].val, unionn(e[i].u, e[i].v);    printf("%d",ans);    return 0;}

拓扑排序

树链剖分

重心

直径

dfs序

LCA

倍增

常数查询

数据结构

数组

链表

队列

有限队列

ST表

手写堆

STL

左偏树

#include <cstdio>#include <cstring>#include <algorithm>#define clr(x) memset(x, 0, sizeof x)#define digit (ch <  '0' || ch >  '9')using namespace std;template <class T> inline void read(T &x) {    int flag = 1; x = 0;    register char ch = getchar();    while( digit) { if(ch == '-')  flag = -1; ch = getchar(); }    while(!digit) { x = (x<<1)+(x<<3)+ch-'0'; ch = getchar(); }    x *= flag;}const int N = 100005;int n, m;int rs[N],ls[N],fa[N],dis[N],str[N];int merge(int x, int y) {    if(!x || !y) return x+y;    if(str[x] < str[y]) swap(x, y);    rs[x] = merge(rs[x], y);    if(dis[rs[x]] > dis[ls[x]]) swap(ls[x], rs[x]);    dis[x] = dis[rs[x]]+1;    fa[ls[x]] = fa[rs[x]] = fa[x] = x;    return x; }int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }int main() {    while(~scanf("%d",&n)) {        clr(ls), clr(rs), clr(dis);        dis[0] = -1;        for(int i = 1; i <= n; i++) read(str[i]), fa[i] = i;        read(m);        int x,y;        while(m--) {            read(x), read(y);            int fx = find(x), fy = find(y);            if(fx == fy) printf( "-1\n" );            else {                str[fx] >>= 1; str[fy] >>= 1;                int hp1 = merge(ls[fx], rs[fx]);                int hp2 = merge(ls[fy], rs[fy]);                ls[fx] = rs[fx] = dis[fx] = 0;                ls[fy] = rs[fy] = dis[fy] = 0;                fx = merge(fx, hp1);                fy = merge(fy, hp2);                int ans = merge(fx, fy);                printf( "%d\n", str[ans] );            }        }    }    return 0;}

树状数组

线段树

莫队

分块

CDQ分治

平衡树

搜索

DFS

BFS

IDDFS

A*

Alpha-Beta

剪枝

最优性剪枝

可行性剪枝

分支定界

字符串

KMP

Trie

manacher

hash

DP

数位DP

状压DP

区间DP

背包

01

完全

部分

树形DP

期望DP

读入优化

链式前向星

差分

前缀和

离散化

位运算

hash

高精度