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
高精度
阅读全文
0 0
- NOIPの模板总结
- NOIP赛前常用模板代码总结
- 灰のNOIP总结
- NOIP模板
- 【NOIP】时间将尽の模板集合
- noip总结
- NOIP总结
- NOIP总结
- NOIP总结
- NOIp总结
- NOIP 考前模板整理
- noip模板整理
- NOIP模板整理
- NOIP 模板整理
- NOIP 前夕 模板整理
- NOIP模板大全
- 【NOIP模板】 tarjan
- 【NOIP模板】KMP
- 共同合伙人的创业
- 按钮
- 制作自己的数据集tfrecord格式
- NOIP2016 && bzoj4719天天爱跑步
- 一首属于程序员的情书。。。。。
- NOIPの模板总结
- CF 803 F Coprime Subsequences (容斥原理)
- 算术运算符的应用
- html拾遗第1天,form 提交
- Vue中filter的使用
- BZOJ 2588 Count on a tree(树上的主席树)
- 树莓派3B创建WiFi热点
- 本地两个PHP项目相互请求
- Java流程控制