数据结构
字符串处理
KMP
1 | /* |
e-KMP
1 | /* |
Z-算法
1 | //求每个位置匹配前缀的长度的最大值 s[0…z[i]-1]=s[i…i+z[i]-1] |
最大最小表达式
1 | int getminmax(bool flag,string s){ |
Manacher
1 | char Ma[maxn*2]; |
Manacher返回最长回文串
1 | string Manacher(string s) { |
字符串哈希
1 | typedef unsigned long long ull; |
1 | p[0]=1; |
回文树
1 | const int MAXN = 100005 ; |
1 | struct PAT{ |
支持前后端插入回文树
1 | struct PAT |
AC自动机
1 | struct Trie{ |
后缀数组
倍增法
1 | struct DA{ |
DC3
1 | struct DA{ |
后缀自动机
1 | struct SAM{ |
树链剖分
1 | int n,q,a[maxn]; |
虚树
1 | 考虑得到了询问点,如何构造出一棵虚树。 |
1 | vector<int>G[maxn]; |
树分治
点分治
1 | int Laxt[maxn<<1],Next[maxn<<1],To[maxn<<1],Len[maxn<<1],ppp; |
不需要容斥的点分治
1 | int a[N], dis[10000003]; |
动态点分治
1 | /* |
可以任意删除元素的优先队列
1 |
|
可持续化字典树
1 | int sum[maxn * 35], son[maxn * 35][2],root[maxn]; |
线段树合并
1 | int ls[maxn*40],rs[maxn*40],rt[maxn*40],num[maxn*40],p; |
主席树
1 | int sum[maxn*40],rt[maxn*40]; |
权值线段树
1 | ll sum[maxn*40],val[maxn*40]; |
主席树套树状数组
1 | ///动态第K大 |
树状数组套主席树 (二维数点)
1 | int n,m; |
可持久化并查集
1 |
|
笛卡尔树
1 | int n,rt; |
二维树状数组
1 | struct BIT2D{ |
图论
前向星
1 | int Next[maxn<<1],To[maxn<<1],Laxt[maxn<<1]; |
深度优先遍历相关
无向图的双连通分量/点双
1 | struct Edge{ |
求无向图的桥和割点
1 |
|
无向图的强连通分量/边双
1 | int Laxt[maxn<<1],Next[maxn<<1],To[maxn<<1],cnt; |
有向图的强连通分量
1 | vector<int>G[maxn]; |
2-SAT匹配
1 | struct TwoSAT{ |
最短路
Dijkstra +单源最短路+记录路径O(mlogn)
1 | struct Edge{ |
BellmanFord (单源最短路判负环)O(nm)
1 | struct Edge |
Floyd 多源最短路 O(n^3)
1 | typedef struct{ |
FLoyd 判最小环
1 | ///算法思想:如果存在最小环,会在编号最大的点u更新最短路径前找到这个环,发现的方法是,更新最短路径前,遍历i,j点对,一定会发现某对i到j的最短路径长度dis[i][j]+mp[j][u]+mp[u][i] != INF,这时i,j是图中挨着u的两个点,因为在之前最短路更新过程中,u没有参与更新,所以dis[i][j]所表示的路径中不会出现u,如果成立,则一定是一个环。用Floyd算法来实现。但是对于负环此算法失效,因为有负环时,dis[i][j]已经不能保证i到j的路径上不会经过同一个点多次了。 |
Floyd 判环(龟兔赛跑算法)
1 | (1)求环 |
最小生成树
有向最小生成树(朱刘算法)
1 | /// 固定根的最小树型图,邻接矩阵写法 |
二分图
理论
1 | 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 |
二分图判断
1 | color[maxn]; |
匈牙利算法(dfs+bfs)
1 | bool dfs(int u){ |
HK算法(优化匈牙利(√N*M))
1 | const int maxn=3300+50; |
二分图最大基数匹配
1 | /// 二分图最大基数匹配 |
二分图最大权匹配(KM算法)
1 | int g[150][150]; ///存图 |
bfs实现的KM
1 | const int N=2e2+50; |
网络流
理论
建模技巧
1 | ##二分图带权最大独立集。 |
上下界网络流建图方法
1 | ## 记号说明 |
Edge
1 | struct Edge |
EdmondKarp
1 | const int maxn = "Edit"; |
Dinic
1 | const int maxn = "Edit"; |
ISAP
1 | const int maxn = "Edit"; |
MinCost MaxFlow
1 | const int maxn = "Edit"; |
sap
1 |
|
LCA
倍增
1 | struct LCA{ |
倍增简单写法
1 | int mi[maxn][22],fa[maxn][22],dep[maxn]; |
RMQ写法
1 | int d[maxn*2][20],dep[maxn],id[maxn],w[maxn],cnt; ///空间要开两倍多 |
树上差分
点差分
1 | //查询每个点没经过的次数 |
边差分
1 | //查询每个边的经过次数 |
数学
拉格朗日插值
普通n^2
1 | ll n,k; |
x取连续时的插值法 复杂度O(n)
1 |
|
差分表
一些公式
1 | //平方和公式 sigm(i^2)=n*(n+1)*(2n+1)/6 |
莫比乌斯反演
组合数计数
1 | inv[0]=p[0]=1; |
卢卡斯定理
1 | ll pow_mod(ll x, ll n, ll mod){ |
逆元
如果mod不是素数 那么a关于mod的逆元是 a^(phi(mod)-1)
ExGcd求逆元
1 | ///返回 d=gcd(a,b); 和对应于等式 ax+by=d 中的 x,y |
费马小定理
1 | ///a<mod 并且 p为素数 |
逆元线性筛
1 | inv[1]=1; |
杜教筛
设需要计算的式子为:$[Math Processing Error]\sum_{i=1}^{n}f(i)(f(i)为积性函数)$
我们构造两个积性函数$h$和$g$。使得$h=f∗g$
现在我们开始求$\sum_{i=1}^{n}h(i)$
记$[Math Processing Error]S(n)=\sum_{i=1}^{n}f(i)$
$\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d|i}g(d)\cdot f(\frac{i}{d})\\\to =\sum_{d=1}^{n}g(d)\cdot\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f({i})$
$[Math Processing Error]\to \sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor)$
接着,我们将右边式子的第一项给提出来,可以得到:
$\sum_{i=1}^{n}h(i)=g(1)\cdot S(n)+\sum_{d=2}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor)$
$\to g(1)S(n)=\sum_{i=1}^{n}h(i)-\sum_{d=2}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor) $
其中$h(i)=(f*g)(i)$
1 |
|
Lucy筛(素数个数 素数和)O(n^4/3)
1 |
|
数论
数论函数基础
合数分解
1 | int prime[maxn+1]; |
欧拉函数
欧拉降幂
A^Bmod C=A^(B mod phji(C)) %C gcd(a,c)==1
A^B mod C=A^B %C (B<phi(C))
A^B mod C=A^(B mod phi(C)+phi(C))%C (B>=phi(C))
得出单个数的欧拉函数 O(sqrt n)
1 | ll euler(ll n) |
筛法欧拉函数
1 | const int N = "Edit"; |
线性筛
1 | bool check[maxn]; |
莫比乌斯
莫比乌斯函数
1 | int prime[maxn]; |
模线性方程
二次剩余
1 | LL w; |
中国剩余定理
1 | ///要求m 两两互质 X=ri(mod mi) 引用返回通解 X=re+k*mo |
ExCRT
1 | //mi可以不两两互质 |
大步小步算法 a^x=b(mod n)
1 | // 求解模方程a^x=b(mod n)。n 为素数。无解返回-1 |
扩展大步小步(gcd!=1)
1 | int ex_BSGS(int A,int B,int C) |
线性基
1 | struct Linear_Basis{ |
几何
知识点
1 | 线段上的整点个数,(x1,y1)(x2,y2)两点连线之间的整点数是gcd(|x1−x2|,|y1−y2|)+1 |
弧度转换,点绕点旋转
欧拉定理:设平面图的顶点数,边数和面数分别为V,E,和F,则V+F-E=2
其中顺时针旋转为负,逆时针旋转为正,角度angle是弧度值,如旋转30度转换为弧度为: $angle = pi/180 * 30$。
4、度与角度的转换
根据圆为$360 º$,弧度为$2π$,即 $360º = 2π$
4.1 角度转弧度:$2π / 360 = π / 180 ≈ 0.0174rad$, 即: $度数 (π / 180) = 弧度$
例如:将30º转为弧度rad
$ 30º (π / 180)= 0.523320 rad $
4.2 弧度转角度: $360 / 2π = 180 / π ≈ 57.3º$, 即: $ 弧度 (180 / π) = 度数$
例如:将$0.523320rad$转为度º
$0.523320rad (180 / π) = 29.9992352688º $
若o不是原点,则可先将a点坐标转换为相对坐标计算,计算结果再加上o点坐标。
参与计算的a点坐标实际应为 a - 0,最终计算公式如下:
$b.x = ( a.x - o.x)cos(angle) - (a.y - o.y)sin(angle) + o.x$
$b.y = (a.x - o.x)sin(angle) + (a.y - o.y)cos(angle) + o.y$
刘汝佳套餐
Point
1 | const double inf=1e200; |
Circle
1 |
|
Polygon
1 |
|
付队模板
1 |
|
球体积交
1 |
|
其他
分块
1 | int n; |
分块的一些技巧
查询区间一个数的个数 (二分
查询区间某数前驱 (二分
在某个位置插入一个数(vector 暴力插入 后定期重构(块大小大于原块的五倍。
bitset
1 | 对于一个叫做bit的bitset: |
斜率DP
画图判断交点的位置决定是否剔除
1 | $dp[i][j]=dp[k][j-1]+(sum[i]-sum[k])-h[k+1]*(w[i]-w[k])$ |
1 | /// |
博弈
威佐夫博弈
1 | scanf("%lld%lld",&a,&b); |
sg函数
1 | int sg[maxn]; |
ST表
1 | int d[maxn][20],a[maxn],n; |
枚举子集
1 | for(int j=x;j;j=(j-1)&x) //枚举所有x的二进制子集 |
SOSDP
1 | for(int i=0;i<4;i++){ ///n*logn 遍历所有子集 |
Prufer序列
理论
1 | 一棵n个节点的无根树唯一地对应了一个长度为n-2的数列,数列中的每个数都在1到n的范围内。 |
1 | prufer数列是一种无根树的编码表示,类似于hash。 |
1 | (2)prufer序列转化为无根树。 |
技巧
JAVA
1 | import java.math.BigDecimal; |
文件读入
1 | freopen("input.txt","r",stdin); |
扩栈
1 | // 解决爆栈问题 |
快速读入
1 | // 适用于正负整数 |
莫队算法
1 | // --- |
1 | //带修莫队,复杂度n^{5/3} |
cdq分治
1 | ///矩形区间加 区间求和 |
整体二分
1 | ///带修查区间第K大 |
高精度
1 | // 加法 乘法 小于号 输出 |
矩阵
矩阵快速幂
1 | typedef vector<ll>vec; |
高斯消元
1 | void gauss() |
数位DP
1 | int num[20]; |