Skip to content

Commit

Permalink
add comments and links
Browse files Browse the repository at this point in the history
  • Loading branch information
EndlessCheng committed May 4, 2020
1 parent ba64358 commit 993273e
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 49 deletions.
12 changes: 12 additions & 0 deletions copypasta/geometry.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ det (determinant,行列式,叉积的模,有向面积):
1rad = (180/π)°
todo 二维偏序 https://ac.nowcoder.com/discuss/394080 F 题
Pick 定理
https://oi-wiki.org/geometry/pick/
https://cp-algorithms.com/geometry/picks-theorem.html
https://cp-algorithms.com/geometry/lattice-points.html
*/

const eps = 1e-8
Expand Down Expand Up @@ -292,6 +297,10 @@ func (o circle) tangents2(b circle) (ls []lineF, hasInf bool) {
// https://en.wikipedia.org/wiki/Inversive_geometry
// TODO: https://oi-wiki.org/geometry/inverse/

// 三角剖分
// todo https://oi-wiki.org/geometry/triangulation/
// https://cp-algorithms.com/geometry/delaunay.html

func vec2Collection() {
readVec := func(in io.Reader) vec {
var x, y int64
Expand Down Expand Up @@ -510,6 +519,9 @@ func vec2Collection() {
return ps[i].sub(ps[i-1]).det(p.sub(ps[i-1])) >= 0
}

// todo 判断点 p 是否在多边形 ps 内部
// 光线投射算法 Ray casting algorithm

// 判断 ∠abc 是否为直角
// 如果是线段的话,还需要判断恰好有四个点,并且没有严格交叉(含重合)
isOrthogonal := func(a, b, c vec) bool { return a.sub(b).dot(c.sub(b)) == 0 }
Expand Down
56 changes: 41 additions & 15 deletions copypasta/graph.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package copypasta

import (
. "container/heap"
"container/heap"
. "fmt"
"io"
"sort"
Expand Down Expand Up @@ -664,6 +664,21 @@ func (*graph) shortestCycleFloydWarshall(weights [][]int64) int64 {
return ans
}

type hPair struct {
dis int64
v int
}
type pairHeap []hPair

func (h pairHeap) Len() int { return len(h) }
func (h pairHeap) Less(i, j int) bool { return h[i].dis < h[j].dis }
func (h pairHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *pairHeap) Push(v interface{}) { *h = append(*h, v.(hPair)) }
func (h *pairHeap) Pop() (v interface{}) { a := *h; *h, v = a[:len(a)-1], a[len(a)-1]; return }
func (h *pairHeap) push(v hPair) { heap.Push(h, v) }
func (h *pairHeap) pop() hPair { return heap.Pop(h).(hPair) }
func (h pairHeap) empty() bool { return len(h) == 0 }

// 单源最短路 Dijkstra
// 适用于稀疏图 O((|E|+|V|)⋅log|V|)
// start 也可以是一个点集,这相当于同时对多个点跑最短路
Expand Down Expand Up @@ -698,10 +713,10 @@ func (*graph) shortestPathDijkstra(in io.Reader, n, m, st int) (dist []int64) {
}

h := &pairHeap{}
Push(h, hPair{0, st})
for h.Len() > 0 {
p := Pop(h).(hPair)
d, v := p.x, p.y
h.push(hPair{0, st})
for !h.empty() {
p := h.pop()
d, v := p.dis, p.v
if dist[v] < d {
continue
}
Expand All @@ -710,7 +725,7 @@ func (*graph) shortestPathDijkstra(in io.Reader, n, m, st int) (dist []int64) {
if newD := dist[v] + e.weight; newD < dist[w] {
dist[w] = newD
fa[w] = v
Push(h, hPair{newD, w})
h.push(hPair{newD, w})
}
}
}
Expand Down Expand Up @@ -744,23 +759,23 @@ func (*graph) shortestPathDijkstra(in io.Reader, n, m, st int) (dist []int64) {
}

h := &pairHeap{}
Push(h, hPair{0, st})
for h.Len() > 0 {
p := Pop(h).(hPair)
d, v := p.x, p.y
h.push(hPair{0, st})
for !h.empty() {
p := h.pop()
d, v := p.dis, p.v
if dist2[v] < d {
continue
}
for _, e := range g[v] {
w := e.to
newD := d + e.weight
if newD < dist[w] {
Push(h, hPair{newD, w})
h.push(hPair{newD, w})
dist[w], newD = newD, dist[w]
}
if newD > dist[w] && newD < dist2[w] {
dist2[w] = newD
Push(h, hPair{newD, w})
h.push(hPair{newD, w})
}
}
}
Expand Down Expand Up @@ -1092,6 +1107,9 @@ func (*graph) bipartiteFindOddLengthCycle(n int, g [][]int) (cycle []int) {
}

// 二分图最大匹配 - 匈牙利算法/增广路算法 O(nm)
// 最大匹配+最小边覆盖=n
// 最大独立集+最小顶点覆盖=n 最大独立集=n-最大匹配
// 最大匹配=最小顶点覆盖
// https://www.renfei.org/blog/bipartite-matching.html 推荐
// https://www.geeksforgeeks.org/maximum-bipartite-matching/
// https://oi-wiki.org/graph/bi-graph/#_9
Expand Down Expand Up @@ -1425,10 +1443,17 @@ func (*graph) treeWithCycle(n int, g [][]int) {
}

/* 网络流
上下界网络流 https://oi-wiki.org/graph/flow/bound/
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/FordFulkerson.java.html
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/FlowNetwork.java.html
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/FlowEdge.java.html
全局最小割 https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/GlobalMincut.java.html
EXTRA: Disjoint paths
Edge-disjoint paths: It turns out that the maximum number of edge-disjoint paths equals the maximum flow of the graph,
assuming that the capacity of each edge is one.
Node-disjoint paths: 拆点法
EXTRA: 路径覆盖 Path cover
todo
*/

// 最大流 Dinic's algorithm O(n2m)
Expand Down Expand Up @@ -1518,9 +1543,10 @@ func (*graph) maxFlowDinic(in io.Reader, n, m, st, end int) (maxFlow int) {
return
}

// TODO 最大流 加强版 / 预流推进
// 预流推进 HLPP 算法(High Level Preflow Push)
// todo https://oi-wiki.org/graph/flow/max-flow/#hlpp
// 模板题 https://www.luogu.com.cn/problem/P4722

// TODO 最小费用最大流
// https://oi-wiki.org/graph/flow/min-cost/
// 最小费用最大流
// todo https://oi-wiki.org/graph/flow/min-cost/
// 模板题 https://www.luogu.com.cn/problem/P3381
56 changes: 52 additions & 4 deletions copypasta/graph_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func (*tree) numPairsWithDistanceLimit(in io.Reader, n int, upperDis int64) int6
// 适用于查询量和节点数等同的情形
// NOTE: 多个点的 LCA 等于 dfn_min 和 dfn_max 的 LCA
// https://oi-wiki.org/graph/lca/#_5
// TODO 模板题 https://www.luogu.com.cn/problem/P3379
// 模板题 https://www.luogu.com.cn/problem/P3379
// 题目推荐 https://cp-algorithms.com/graph/lca.html#toc-tgt-2
// TODO log 优化
func (*tree) lcaBinarySearch(n, root int, g [][]int) {
Expand Down Expand Up @@ -422,6 +422,57 @@ func (*tree) lcaRMQ(n, root int, g [][]int) {
_ = _d
}

// 最近公共祖先 - 其三 - Tarjan 离线算法
// 时间和空间复杂度均为 O(n+q)
// https://oi-wiki.org/graph/lca/#tarjan
// https://cp-algorithms.com/graph/lca_tarjan.html
func (*tree) lcaTarjan(n, root int, g [][]int, _qs [][2]int) []int {
fa := make([]int, n)
for i := range fa {
fa[i] = i
}
var find func(int) int
find = func(x int) int {
if fa[x] != x {
fa[x] = find(fa[x])
}
return fa[x]
}

q := len(_qs) // read
lca := make([]int, q)
type query struct{ w, i int }
qs := make([][]query, n)
vis := make([]int8, n)
var f func(int)
f = func(v int) {
vis[v] = 1
for _, w := range g[v] {
if vis[w] == 0 {
f(w)
fa[w] = v
}
}
for _, q := range qs[v] {
if w := q.w; vis[w] == 2 {
lca[q.i] = find(w)
}
}
vis[v] = 2
}
for i := range lca {
x, y := _qs[i][0], _qs[i][1] // read
if x != y {
qs[x] = append(qs[x], query{y, i})
qs[y] = append(qs[y], query{x, i})
} else {
lca[i] = x
}
}
f(root)
return lca
}

// LCA 应用:树上差分
// 操作为更新 v-w 路径上的点权或边权(初始为 0)
// 点权时 diff[lca] -= val
Expand Down Expand Up @@ -558,9 +609,6 @@ func (*tree) hld(n, root int, g [][]int, vals []int64) {
// TODO: 虚树
// https://oi-wiki.org/graph/virtual-tree/

// 基环树
// TODO

// 仙人掌图 Cactus graph
// A connected graph in which any two simple cycles have at most one vertex in common
// https://en.wikipedia.org/wiki/Cactus_graph
Expand Down
7 changes: 5 additions & 2 deletions copypasta/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
)

// 带有 IO 缓冲区的输入输出,适用于绝大多数题目
func bufferIO(_r io.Reader, _w io.Writer) {
// NOTE: just a bufio.Reader is enough, there is no difference between this and ioutil.ReadAll
in := bufio.NewReader(_r)
Expand All @@ -20,7 +21,8 @@ func bufferIO(_r io.Reader, _w io.Writer) {
// NOTE: to print []byte as string, use Fprintf(out, "%s", data) or Fprint(out, string(data))
}

// 相比 Fscan,每读入 1e5 个 int 可以加速 40-50ms
// 快读,适用于输入量超过 1e6 的题目
// 相比 Fscan,每读入 1e6 个 int 可以加速 400ms 左右
func fastIO(_r io.Reader, _w io.Writer) {
in := bufio.NewScanner(_r)
in.Split(bufio.ScanWords)
Expand Down Expand Up @@ -56,7 +58,8 @@ func fastIO(_r io.Reader, _w io.Writer) {
_ = []interface{}{read, readS}
}

// 性能测试 CF1276B 1e6 数据量
// 超快读
// 以 CF1276B(1e6 数据量)为例,测试结果如下:
// bufferIO 670 ms
// fastIO 296 ms
// fasterIO 202 ms
Expand Down
70 changes: 48 additions & 22 deletions copypasta/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func numberTheoryCollection() {
return
}

type pair struct{ x, y int64 }
frac := func(a, b int64) pair { g := gcd(a, b); return pair{a / g, b / g} }

// 给定数组,统计所有区间的 GCD 值
// 返回 map[GCD值]等于该值的区间个数
cntRangeGCD := func(arr []int64) map[int64]int64 {
Expand Down Expand Up @@ -369,6 +372,15 @@ func numberTheoryCollection() {
// https://oeis.org/A199337 Number of highly composite numbers not divisible by n
// https://www.luogu.com.cn/problem/P1463

// TIPS: Maximal number of divisors (d(n)) of any n-digit number
// 方便估计复杂度 - 近似为开立方
// https://oeis.org/A066150
// 4, 12, 32, 64, 128, 240, 448, 768, 1344, /* 9 */
// 2304, 4032, 6720, 10752, 17280, 26880, 41472, 64512, 103680, 161280 /* 19 */

// Smallest number with exactly n divisors
// https://oeis.org/A005179

// 预处理: [2,mx] 范围内数的不同质因子,例如 factors[12] = [2,3]
// for i>=2, factors[i][0] == i means i is prime
primeFactorsAll := func() {
Expand Down Expand Up @@ -786,7 +798,8 @@ func numberTheoryCollection() {
// 模板题 https://www.luogu.com.cn/problem/P4720
// 古代猪文 https://www.luogu.com.cn/problem/P2480

//
// 原根
// todo https://cp-algorithms.com/algebra/primitive-root.html

// 莫比乌斯函数
// todo
Expand Down Expand Up @@ -838,7 +851,7 @@ func numberTheoryCollection() {
_ = []interface{}{
primes,
sqCheck, cubeCheck, sqrt, cbrt,
mul, muls, gcds, lcm, cntRangeGCD,
mul, muls, gcds, lcm, frac, cntRangeGCD,
isPrime, sieve, primeFactorization, primeDivisors, primeExponentsCountAll,
divisors, divisorPairs, doDivisors, doDivisors2, maxSqrtDivisor, divisorsAll, primeFactorsAll, lpfAll, distinctPrimesCountAll, calcPhi, phiAll,
exgcd, invM, invP, divM, divP, crt, excrt, babyStepGiantStep,
Expand All @@ -847,26 +860,32 @@ func numberTheoryCollection() {
}
}

// 组合、杂项
// 一些组合恒等式的解释 https://www.zhihu.com/question/26094736
// C(n, k) - C(n-1, k) = C(n-1, k-1)
// 隔板法 https://zh.wikipedia.org/wiki/%E9%9A%94%E6%9D%BF%E6%B3%95
// 圆排列 https://zh.wikipedia.org/wiki/%E5%9C%86%E6%8E%92%E5%88%97
// 可重集排列
// 可重集组合 todo https://codeforces.ml/problemset/problem/451/E
// 错排 https://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98
// 范德蒙德恒等式 https://zh.wikipedia.org/wiki/%E8%8C%83%E5%BE%B7%E8%92%99%E6%81%92%E7%AD%89%E5%BC%8F
// 二阶递推数列通项 https://zhuanlan.zhihu.com/p/75096951
// 斯特林数 https://blog.csdn.net/ACdreamers/article/details/8521134
// Stirling numbers of the first kind, s(n,k) https://oeis.org/A008275
// 将 n 个元素排成 k 个非空循环排列的方法数
// s(n,k) 的递推公式: s(n,k)=(n-1)*s(n-1,k)+s(n-1,k-1), 1<=k<=n-1
// 边界条件:s(n,0)=0, n>=1 s(n,n)=1, n>=0
// Stirling numbers of the second kind, S2(n,k) https://oeis.org/A008277
// 将 n 个元素拆分为 k 个非空集的方法数
// S2(n, k) = (1/k!) * Sum_{i=0..k} (-1)^(k-i)*binomial(k, i)*i^n.
// S2(n,k) 的递推公式:S2(n,k)=k*S2(n-1,k)+S2(n-1,k-1), 1<=k<=n-1
// 边界条件:S(n,0)=0, n>=1 S(n,n)=1, n>=0
/* 组合、杂项
一些组合恒等式的解释 https://www.zhihu.com/question/26094736
C(n, k) - C(n-1, k) = C(n-1, k-1)
隔板法 https://zh.wikipedia.org/wiki/%E9%9A%94%E6%9D%BF%E6%B3%95
圆排列 https://zh.wikipedia.org/wiki/%E5%9C%86%E6%8E%92%E5%88%97
可重集排列
可重集组合 todo https://codeforces.ml/problemset/problem/451/E
错排 https://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98
范德蒙德恒等式 https://zh.wikipedia.org/wiki/%E8%8C%83%E5%BE%B7%E8%92%99%E6%81%92%E7%AD%89%E5%BC%8F
二阶递推数列通项 https://zhuanlan.zhihu.com/p/75096951
斯特林数 https://blog.csdn.net/ACdreamers/article/details/8521134
Stirling numbers of the first kind, s(n,k) https://oeis.org/A008275
将 n 个元素排成 k 个非空循环排列的方法数
s(n,k) 的递推公式: s(n,k)=(n-1)*s(n-1,k)+s(n-1,k-1), 1<=k<=n-1
边界条件:s(n,0)=0, n>=1 s(n,n)=1, n>=0
Stirling numbers of the second kind, S2(n,k) https://oeis.org/A008277
将 n 个元素拆分为 k 个非空集的方法数
S2(n, k) = (1/k!) * Sum_{i=0..k} (-1)^(k-i)*binomial(k, i)*i^n.
S2(n,k) 的递推公式:S2(n,k)=k*S2(n-1,k)+S2(n-1,k-1), 1<=k<=n-1
边界条件:S(n,0)=0, n>=1 S(n,n)=1, n>=0
凯莱公式 Cayley’s formula: the number of trees on n labeled vertices is n^(n-2).
普吕弗序列 Prüfer sequence: 由树唯一地产生的序列
约瑟夫问题 Josephus Problem https://cp-algorithms.com/others/josephus_problem.html https://en.wikipedia.org/wiki/Josephus_problem
Stern-Brocot 树与 Farey 序列 https://oi-wiki.org/misc/stern-brocot/ https://cp-algorithms.com/others/stern_brocot_tree_farey_sequences.html
矩阵树定理 基尔霍夫定理 Kirchhoff‘s theorem https://en.wikipedia.org/wiki/Kirchhoff%27s_theorem
*/
func miscCollection() {
// n married couples are seated in a row so that every wife is to the left of her husband
// 若不考虑顺序,则所有排列的个数为 (2n)!
Expand Down Expand Up @@ -1014,6 +1033,12 @@ func miscCollection() {
// 此时对手的状态为必败状态——对手必定是失败的,而相反地,自己就获得了胜利
// 对于定理 3,如果不存在一个后继状态为必败状态,那么无论如何,玩家只能操作到必胜状态;
// 此时对手的状态为必胜状态——对手必定是胜利的,自己就输掉了游戏
// The Sprague–Grundy theorem generalizes the strategy used in nim to all games that fulfil the following requirements:
// - There are two players who move alternately.
// - The game consists of states, and the possible moves in a state do not depend on whose turn it is.
// - The game ends when a player cannot make a move.
// - The game surely ends sooner or later.
// - The players have complete information about the states and allowed moves, and there is no randomness in the game.
// 推荐 https://blog.csdn.net/acm_cxlove/article/details/7854530
// https://oi-wiki.org/math/game-theory/
// 个人写的总结 https://github.com/SDU-ACM-ICPC/Qiki/blob/master/%E5%8D%9A%E5%BC%88%E8%AE%BA(Game%20Theory).md
Expand Down Expand Up @@ -1053,6 +1078,7 @@ func gameTheoryCollection() {
// Sprague-Grundy theorem
// 有向图游戏的某个局面必胜 <=> 该局面对应节点的 SG 函数值 > 0
// 有向图游戏的某个局面必败 <=> 该局面对应节点的 SG 函数值 = 0
// 推荐资料 Competitive Programmer’s Handbook Ch.25
// https://oi-wiki.org/math/game-theory/#sg
// https://en.wikipedia.org/wiki/Sprague%E2%80%93Grundy_theorem
// https://cp-algorithms.com/game_theory/sprague-grundy-nim.html
Expand Down
3 changes: 2 additions & 1 deletion copypasta/math_matrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@ func (matrix) inv(in io.Reader, n int) matrix {
return ans
}

// 高斯消元
// 行列式 高斯消元 Determinant
// TODO https://oi-wiki.org/math/gauss/
// https://cp-algorithms.com/linear_algebra/determinant-gauss.html
// https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/GaussianElimination.java.html
// https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/GaussJordanElimination.java.html

Expand Down
Loading

0 comments on commit 993273e

Please sign in to comment.