diff --git a/algorithms/graph/hld.cpp b/algorithms/graph/hld.cpp
index 73908ce0699743c5f380c875b979d8c8d4258e14..2d9f871a0947fd4ce43eef80189a2deb72cc0f2f 100644
--- a/algorithms/graph/hld.cpp
+++ b/algorithms/graph/hld.cpp
@@ -1,5 +1,16 @@
 /// Heavy Light Decomposition
 ///
+/// Description:
+///   The Heavy Light Decomposition splits a tree into several path so that we
+/// can reach the root from any node by traversing at most $\log n$ paths. For
+/// every vertice $v$, an edge is called heavy if it leads to a child with the
+/// largest subtree size; all other edges are called light. \par
+///   The set of disjoint paths containing heavy edges are called the ``heavy
+/// chains''. These paths (both heavy and light) can be indexed by a single 
+/// segment tree, allowing fast queries and updates to edges (or vertices). And
+/// also, information about the chains (such as the head), allows for fast 
+/// traversals from any node to any of its ancestors.
+///
 /// Time: 
 ///   - build: O(n log n)
 ///   - query: O(log^2 n)
@@ -7,7 +18,7 @@
 /// Space: O(n log n)
 /// 
 /// Caution:
-///   - Modifications are necessary if values are associated to vertices;
+///   - Modifications are necessary if values are associated with vertices;
 ///   - Modifications are necerrary if other data structure is used.
 /// 
 /// Status: Tested (QTREE,URI2887)
diff --git a/algorithms/graph/kruskal.cpp b/algorithms/graph/kruskal.cpp
index 2f86011a94ce12f60d1404de51dafb67426db106..87c4f68092877111e69835b0025206e3513a1546 100644
--- a/algorithms/graph/kruskal.cpp
+++ b/algorithms/graph/kruskal.cpp
@@ -15,10 +15,11 @@ struct Kruskal {
 
   Kruskal(int N) : N(N), ds(N) {}
 
-  int run(vector<iii> &mst) {
+  // Minimum Spanning Tree: comp = less<int>()
+  // Maximum Spanning Tree: comp = greater<int>()
+  int run(vector<iii> &mst, function<bool(int,int)> comp) {
     sort(all(edges), [&](const iii &a, const iii &b) {
-      // ('>' for maximum spanning tree)
-      return a.se < b.se;
+      return comp(a.se, b.se);
     });
 
     int size = 0;
diff --git a/algorithms/graph/lca.cpp b/algorithms/graph/lca.cpp
index d16ddec7782c7f1e1300287459abbb501ad0fba2..2c5da885748122ff831226178cad19180838ac1b 100644
--- a/algorithms/graph/lca.cpp
+++ b/algorithms/graph/lca.cpp
@@ -4,13 +4,13 @@
 ///   The LCA between two nodes in a tree is a node that is an ancestor to both
 /// nodes with the lowest height possible. \par
 ///   The algorithm works by following the path up the tree from both nodes 
-/// "simultaneously" until a common node is found. The naive approach for that
-/// would be $O(n)$ in the worst case. To improve that, this implementation 
-/// uses "binary lifting" which is a way of figuring out the right number of 
-/// up-moves needed to find the LCA by following the binary representation of
-/// the distance to the destination (similar to the "binary search by jumping"),
-/// but, for that, a preprocessing must be done to set every parent at a $2^i$
-/// distance.
+/// ``simultaneously'' until a common node is found. The naive approach for 
+/// that would be $O(n)$ in the worst case. To improve that, this 
+/// implementation uses ``binary lifting'' which is a way of figuring out the 
+/// right number of up-moves needed to find the LCA by following the binary 
+/// representation of the distance to the destination (similar to the ``binary 
+/// search by jumping''), but, for that, a preprocessing must be done to set
+/// every parent at a $2^i$ distance.
 ///
 /// Time:
 ///   - preprocess: O(V log V)
diff --git a/algorithms/math/big_integer.cpp b/algorithms/math/big_integer.cpp
index e2fed1ae433427cf402759cb28cab6686577e200..de456fb68682bb53bfe43949cf00f2554571926a 100644
--- a/algorithms/math/big_integer.cpp
+++ b/algorithms/math/big_integer.cpp
@@ -2,13 +2,13 @@
 ///
 /// Space: O(n)
 ///
-/// Status: Tested (KRAKOVIA)
-//
 /// Caution: 
-///   - Just use python.
-//
+///   - Just use Python if possible.
+///
 /// Include:
 ///  - math/karatsuba
+///
+/// Status: Tested (KRAKOVIA)
 
 const int base = 1000000000;
 const int base_d = 9;
diff --git a/algorithms/math/binary_exponentiation.cpp b/algorithms/math/binary_exponentiation.cpp
index ca57045ee532f2f2d1ad3f4589205e7f431905dc..818f7dd00075b8ae22fcc1fbe49ab939ea960e80 100644
--- a/algorithms/math/binary_exponentiation.cpp
+++ b/algorithms/math/binary_exponentiation.cpp
@@ -1,5 +1,13 @@
 /// Binary Exponentiation
 /// 
+/// Description:
+///   Computes fast exponentiation by looking a the binary representation of
+/// the exponent. The usage of ``bin\_mul'' is not necessary, but it ensures 
+/// that no overflow will occur when multiplying two large integers. It is
+/// definitely required in order to work with Miller-Rabin and Pollard's
+/// Rho implementations (when dealing with numbers that might go up to 
+/// $10^{18}$.
+///
 /// Time: O(log n)
 /// Space: O(1)
 
diff --git a/algorithms/math/legendre.cpp b/algorithms/math/legendre.cpp
index d470908d161049f9266b42a289f753c97b7961b4..7be0e3ce634cc3abda321ed3268883ba7c366bae 100644
--- a/algorithms/math/legendre.cpp
+++ b/algorithms/math/legendre.cpp
@@ -1,5 +1,16 @@
 /// Legendre's Formula
 ///
+/// Description:
+///   Given an interger $n$ and a prime number $p$, find the largest power of
+/// $p$ ($x$) such that $n!$ is divisible by $k^x$. \par
+///   Writing $n!$ as $1 \cdot 2 \cdot 3 ... (n-1) \cdot n$ shows that every
+/// $k$-th element of the product is divisible by $k$ (i.e. adds $1$ to the
+/// answer), the number of such elements is $\lfloor\frac{n}{k}\rfloor$. The 
+/// same is true for every $k^i$, thus, the answer is given by: 
+/// \[ \lfloor\frac{n}{k}\rfloor + \lfloor\frac{n}{k^2}\rfloor + ... + 
+/// \lfloor\frac{n}{k^i}\rfloor \] only approximately the first $log_p n$
+/// elements are greater than zero, therefore the sum is finite.
+///
 /// Time: O(log_p n)
 /// Space: O(1)
 
diff --git a/algorithms/math/linear_diophantine_equation.cpp b/algorithms/math/linear_diophantine_equation.cpp
index 085d7d7e13a185dd9a0c7194b5d9e9411b512084..e523f2558ea5bfb4693febbb70f0f532e4ebe7b5 100644
--- a/algorithms/math/linear_diophantine_equation.cpp
+++ b/algorithms/math/linear_diophantine_equation.cpp
@@ -1,7 +1,7 @@
 /// Linear Diophantine Equation
 ///
 /// Description:
-///   A Linear Diophantine Equation is an equation in the form $ax + by = c$.
+///   A Linear Diophantine Equation is an equation in the form \[ ax + by = c \]
 /// A solution of this equation is a pair $(x,y)$ that satisfies the equation. 
 /// The locus of (lattice) points whose coordinates $x$ and $y$ satisfy the 
 /// equation is a straigh line. \par
diff --git a/algorithms/math/modular_multiplicative_inverse.cpp b/algorithms/math/modular_multiplicative_inverse.cpp
index a06e950382a7db8540c9d620f502159d7e87715e..f1024e2609b9619f1497db8afd1104ad768be86e 100644
--- a/algorithms/math/modular_multiplicative_inverse.cpp
+++ b/algorithms/math/modular_multiplicative_inverse.cpp
@@ -1,5 +1,10 @@
 /// Modular Multiplicative Inverse
 ///
+/// Description:
+///   Given integers $a$ and $m$, the modular multiplicative inverse of $a$ is
+/// an integer $x$ such that \[ a \cdot x \equiv 1 \pmod{m} \] also denoted as
+/// $a^{-1}$.
+///
 /// Time: O(log m)
 /// Space: O(1)
 
diff --git a/algorithms/paradigm/ternary_search.cpp b/algorithms/paradigm/ternary_search.cpp
index a687284e3c0b4225e0defb745e3fb45cd651f68c..457f407c35cdb56aca1443c253ecdf5d972917ac 100644
--- a/algorithms/paradigm/ternary_search.cpp
+++ b/algorithms/paradigm/ternary_search.cpp
@@ -1,30 +1,33 @@
 /// Ternary Search
 ///
+/// Description:
+///   Searches for the minimum (or maximum) value of a unimodal function
+/// $f(x)$ for $x$ between $l$ and $r$.
+///
 /// Time: O(log n)
 /// Space: O(1)
+///
+/// Caution:
+///   - f must be a unimodal function
 
-// Unimodal function 
-double f(double x) {
-  return x * x;
-}
-
-double ternary_search(double l, double r) {
-  double rt, lt;
+// Minimum of f: comp = less<T>()
+// Maximum of f: comp = greater<T>()
+template <typename T, class F = function<T(T)>>
+T ternary_search(T l, T r, F f, function<bool(T,T)> comp) {
+  T rt, lt;
 
   for (int i = 0; i < 500; ++i) {
     if (fabs(r - l) < EPS)
-      return (l + r) / 2.0;
+      return (l + r) / 2;
 
-    lt = (r - l) / 3.0 + l;
-    rt = ((r - l) * 2.0) / 3.0 + l;
+    lt = (r - l) / 3 + l;
+    rt = ((r - l) * 2) / 3 + l;
 
-    // '<' for minimum of f,
-    // '>' for maximum of f
-    if (f(lt) < f(rt))
+    if (comp(f(lt), f(rt)))
       l = lt;
     else
       r = rt;
   }
 
-  return (l + r) / 2.0;
+  return (l + r) / 2;
 }
diff --git a/algorithms/string/booth.cpp b/algorithms/string/booth.cpp
index ca072deea1dcf2dfb2351ee95b9fef03bf485953..19a684e232044c0d8fb7588eee1d3c2958284bb2 100644
--- a/algorithms/string/booth.cpp
+++ b/algorithms/string/booth.cpp
@@ -9,7 +9,9 @@
 /// Time: O(n)
 /// Space: O(n)
 
-string booth(string s) {
+// Maximal: func = greater<char>()
+// Minimal: func = less<char>()
+string booth(string s, function<bool(char,char)> func) {
   string S = s + s;
   vector<int> f(S.size(), -1);
 
@@ -19,13 +21,13 @@ string booth(string s) {
     int i = f[j - k - 1];
 
     while (i != -1 && sj != S[k+i+1]) {
-      if (sj < S[k + i + 1]) // >: maximal
+      if (func(sj, S[k + i + 1]))
         k = j - i - 1;
       i = f[i];
     }
 
     if (sj != S[k+i+1]) {
-      if (sj < S[k]) // >: maximal
+      if (func(sj, S[k]))
         k = j;
 
       f[j-k] = -1;
diff --git a/algorithms/structure/mo_algorithm.cpp b/algorithms/structure/mo_algorithm.cpp
index c174c545fdf5d7e38ff06789f388f2b8275922b5..64803b3910424fb04a3d24c885615a14264dd5da 100644
--- a/algorithms/structure/mo_algorithm.cpp
+++ b/algorithms/structure/mo_algorithm.cpp
@@ -2,6 +2,9 @@
 ///
 /// Time: O((n + q) * sqrt{n})
 /// Space: O(n + q)
+///
+/// Caution:
+///   - Remember to implement add, remove, and get\_ans functions.
 
 struct Query {
   int l, r, idx;
diff --git a/algorithms/structure/trie.cpp b/algorithms/structure/trie.cpp
index a5053daeb4da554b4cbd30c4d1e8b0765cc0c711..6952a693689e9ccd5464615e19eab939e0f63da6 100644
--- a/algorithms/structure/trie.cpp
+++ b/algorithms/structure/trie.cpp
@@ -4,6 +4,9 @@
 ///   - insert: O(M)
 ///   - search: O(M)
 /// Space: O(alph * N)
+///
+/// Caution:
+///   - If Trie stores integers, remember to check order of bits (most/least significant first).
 
 template <typename T>
 struct Trie {
diff --git a/caderno.pdf b/caderno.pdf
index 9e2f1bbe431a7791d341b4676e517309295b6130..9ff400bb0e5ec636c3703ff24aae3ac55aaf119c 100644
Binary files a/caderno.pdf and b/caderno.pdf differ
diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py
index 01a79e8825fbbff5d28765507559695407b9e1b2..e42019db71aa5baa65d54784814bf370e45bae5a 100644
--- a/notebook/gen_latex.py
+++ b/notebook/gen_latex.py
@@ -117,7 +117,7 @@ class LatexGenerator:
             def to_big_o(expr):
                 expr = expr.replace('O', '\\mathcal{O}')
                 expr = expr.replace('log', '\\log')
-                expr = expr.replace('*', '\\times')
+                expr = expr.replace('*', '\\cdot')
                 expr = expr.replace('sqrt', '\\sqrt')
                 return expr