两个数有: \(gcd(a,b)\times lcm(a,b)=a\times b\)
求两个数的最小公倍数,先求出最大公约数即可。
多个数: 当我们求出两个数的 \(gcd\) 时,求最小公倍数是 \(O(1)\) 的复杂度。那么对于多个数,我们其实没有必要求一个共同的最大公约数再去处理,最直接的方法就是,当我们算出两个数的 \(gcd\),或许在求多个数的 \(gcd\) 时候,我们将它放入序列对后面的数继续求解,那么,我们转换一下,直接将最小公倍数放入序列即可
两个数有: \(gcd(a,b)\times lcm(a,b)=a\times b\)
求两个数的最小公倍数,先求出最大公约数即可。
多个数: 当我们求出两个数的 \(gcd\) 时,求最小公倍数是 \(O(1)\) 的复杂度。那么对于多个数,我们其实没有必要求一个共同的最大公约数再去处理,最直接的方法就是,当我们算出两个数的 \(gcd\),或许在求多个数的 \(gcd\) 时候,我们将它放入序列对后面的数继续求解,那么,我们转换一下,直接将最小公倍数放入序列即可
P3379 【模板】最近公共祖先(LCA) - 洛谷 ## 简介 LCA --算法竞赛专题解析(29) - 罗勇军999 - 博客园 Lowest Common Ancestor LCA 是指在一棵树中,距离两个点最近的两者的公共节点。也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共的节点中,深度尽量深的点。还可以表示成另一种说法,就是如果把树看成是一个图,这找到这两个点中的最短距离。 定义 性质 LCA 算法有在线算法也有离线算法,所谓的在线算法就是实时性的,而离线算法则是要求一次性读入所有的请求,然后在统一得处理。而在处理的过程中不一定是按照请求的输入顺序来处理的。说不定后输入的请求在算法的执行过程中是被先处理的。
这里主要是讨论 tarjan 算法|与|倍增算法(待更)与树链剖分(需要学到高级数据结构(待更))的做法,这三种可以解决几乎所有问题。倍增和树链剖分用的尤其多。具体其他做法看 oi. wiki 即可
最近公共祖先 (Lowest Common Ancestor) - 知乎有详细说明 也可以看董晓算法的视频 322 Tarjan算法 P3379【模板】最近公共祖先(LCA)_哔哩哔哩_bilibili 董晓算法很详细的讲了三种方法:倍增,tarjan,树链剖分,甚至更深入的知识。
1 | #include <bits/stdc++.h> |
\(Johnson\) 算法则通过另外一种方法来给每条边重新标注边权。
我们新建一个虚拟节点(在这里我们就设它的编号为 \(0\))。从这个点向其他所有点连一条边权为 \(0\) 的边。
接下来用 \(Bellman-Ford\) 算法求出从 \(0\) 号点到其他所有点的最短路,记为 \(h_i\)。
假如存在一条从 \(u\) 点到 \(v\) 点,边权为 \(w\) 的边,则我们将该边的边权重新设置为 \(w+h_u-h_v\)。
1 | //可以生成一个序列 |
1 | //output |
递归求法:
1 | //用的最多 |
1 | int gcd(int a, int b) { |
C++14 可用 __gcd (a, b)
[[图论/链式前向星存图]] # 堆优化版 :\(O(mlogm)\)
1 | #include <bits/stdc++.h> |
在某些题有奇效
1 | //1.默认构造函数 :0 |
运算符重载[], 支持下标从 0 开始访问, 与数组类似
示例 P1020 导弹拦截 用到了求最长下降子序列和最长上升子序列 ,还用到了 \(Dilworth 定理\) 证明第二问是最长上升子序列。
若 \(n=0\),则需要特判。 # 最长上升子序列
目前我笔记有三种写法,第一种即可。 推荐 1
1 | #include<bits/stdc++.h>//标准模板 |
推荐 2
P1439【模板】最长公共子序列 下面的模板代码只适用于每个数字只出现一次。 ## 1 【模板】最长公共子序列: \(O(nlogn)\) ### 1.1 模板:[[最长上升子序列|LIS]] 的应用 [[最长上升子序列]]
1 | #include <bits/stdc++.h> |
1 | # 1.2 #include <bits/stdc++.h> |