diff --git a/caderno.pdf b/caderno.pdf
index ec8f0d360fd18a194fae9d1448a4269a19a65092..df4efc6e241440cbb102cc7850d3e8487d05652a 100644
Binary files a/caderno.pdf and b/caderno.pdf differ
diff --git a/caderno/caderno.tex b/caderno/caderno.tex
index 116c6e61665146a51579362b37759e57decdc148..0e3a8e4ffd203ea7a4224774beac4a83d383caa2 100644
--- a/caderno/caderno.tex
+++ b/caderno/caderno.tex
@@ -287,11 +287,6 @@ para $a$ e $m$ coprimos.
 \subsection{Stoer-Wagner}
 \importsource{stoer-wagner.h}
 
-\subsection{SPFA*}
-
-\subsection{BFS 0-1}
-\importsource{bfs01.h}
-
 \subsection{Emparelhamento estável}
 \begin{tabular}{l}
   \hline
@@ -300,9 +295,11 @@ para $a$ e $m$ coprimos.
 \end{tabular}
 \importsource{stable-matching.h}
 
-\subsection{Fluxo máximo*}
+\subsection{Fluxo máximo}
+\importsource{ffek.h}
 
-\subsection{Fluxo de custo mínimo*}
+\subsection{Fluxo de custo mínimo}
+\importsource{ffekmincost.h}
 
 \subsection{Busca em profundidade recursiva}
 \importsource{dfsrec.h}
@@ -313,23 +310,26 @@ para $a$ e $m$ coprimos.
 \subsection{Busca em largura}
 \importsource{bfs.h}
 
-\subsection{Conectado*}
-\importsource{connected.cpp}
+\subsection{Busca em largura 0-1}
+\importsource{bfs01.h}
 
-\subsection{Componentes fortes -- Tarjan*}
-\importsource{tarjan.cpp}
+\subsection{Componentes fortes -- Tarjan}
+\importsource{tarjan.h}
 
-\subsection{Componentes fortes -- Kosaraju*}
-\importsource{kosaraju.cpp}
+\subsection{Componentes fortes -- Kosaraju}
+\importsource{kosaraju.h}
 
 \subsection{Caminho mínimo -- Dijkstra}
 \importsource{dijkstra.h}
 
-\subsection{Caminho mínimo -- Bellman-Ford*}
-\importsource{bellman-ford.cpp}
+\subsection{Caminho mínimo -- Bellman-Ford}
+\importsource{bellman-ford.h}
+
+\subsection{Caminho mínimo -- SPFA}
+\importsource{spfa.h}
 
-\subsection{Caminhos mínimos -- Floyd-Warshall*}
-\importsource{floyd-warshall.cpp}
+\subsection{Caminhos mínimos -- Floyd-Warshall}
+\importsource{floyd-warshall.h}
 
 \subsection{Ordenação Topológica}
 \importsource{topo.h}
@@ -340,12 +340,11 @@ para $a$ e $m$ coprimos.
 \subsection{Árvore geradora mínima -- Kruskal}
 \importsource{kruskal.h}
 
-\subsection{Ascensão binária*}
-\importsource{binary-lifting.cpp}
-
-\subsection{Menor anc. comum -- Ancensão binária*}
+\subsection{Ascensão binária}
+\importsource{bl.h}
 
-\subsection{Menor anc. comum -- Dec. pesado-leve*}
+\subsection{Menor anc. comum -- Ancensão binária}
+\importsource{bllca.h}
 
 \subsection{Decomposição pesado-leve}
 \begin{tabular}{l|l}
@@ -368,9 +367,11 @@ para $a$ e $m$ coprimos.
 \subsection{Menor anc. comum -- Dec. raiz quad.}
 \importsource{stdtlca.h}
 
-\subsection{Empar. máximo bipartido -- Kuhn*}
+\subsection{Empar. máximo bipartido -- Kuhn}
+\importsource{kuhn.h}
 
-\subsection{Empar. máximo bipartido -- Hopcroft*}
+\subsection{Empar. máximo bipartido -- Hopcroft}
+\importsource{hopcroft.h}
 
 \section{Matemática}
 
@@ -433,8 +434,61 @@ ax + by = c
 \end{tabular}
 \importsource{factorize.h}
 
-\subsection{Crivo de Eratóstenes*}
-\importsource{sieve-of-eratosthenes.cpp}
+\subsection{Crivo de Eratóstenes}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg\lg n)$ \\
+\hline
+\end{tabular}
+\importsource{sieve.h}
+
+\subsection{Crivo de número de divisores}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg n)$ \\
+\hline
+\end{tabular}
+\importsource{divisors.h}
+
+\subsection{Crivo de soma dos divisores}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg n)$ \\
+\hline
+\end{tabular}
+\importsource{sumdivsieve.h}
+
+\subsection{Totiente de Euler}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg \lg n)$ \\
+\hline
+\end{tabular}
+\importsource{euler-totient.h}
+
+\subsection{Crivo de soma dos divisores}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg n)$ \\
+\hline
+\end{tabular}
+\importsource{sumdivsieve.h}
+
+\subsection{Crivo de maior divisor primo}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n \lg n)$ \\
+\hline
+\end{tabular}
+\importsource{bigpsieve.h}
+
+\subsection{Crivo linear}
+\begin{tabular}{l}
+  \hline
+  $\bigO(n)$ \\
+\hline
+\end{tabular}
+\importsource{linearsieve.h}
 
 \subsection{Exponenciação binária*}
 \importsource{binary-pow.h}
@@ -448,9 +502,6 @@ ax + by = c
 
 \subsection{Teorema chinês do resto*}
 
-\subsection{Totiente de Euler*}
-\importsource{euler-totient.h}
-
 \subsection{Fibonacci*}
 
 \subsection{Teorema chinês do resto generalizado*}
diff --git a/fontes/acs.h b/fontes/acs.h
index 4357d14f88e0dda436c0135bdc5bc90b2506609e..03c52dbeb9a7d68817f6ced4cfbee301f3aa197c 100644
--- a/fontes/acs.h
+++ b/fontes/acs.h
@@ -1,67 +1,67 @@
 struct node {
-    int p, pc, depth, lnk, out, occ;
-    bool leaf;
-    vector<int> nxt, go, ix;
+  int p, pc, depth, lnk, out, occ;
+  bool leaf;
+  vector<int> nxt, go, ix;
 
-    node() : p (0), pc (0), depth (-1),
-        lnk (-1), out (-1), occ (0),
-        leaf (false), nxt (S, -1), go (S, -1) {}
+  node() : p (0), pc (0), depth (-1),
+  lnk (-1), out (-1), occ (0),
+  leaf (false), nxt (S, -1), go (S, -1) {}
 };
 
 vector<node> aca (1);
 void ins(string ne, int ix) {
-    int u = 0;
-    for (int i = 0; i < ne.size(); i++) {
-        int ch = to_i(ne[i]);
-        if (aca[u].nxt[ch] == -1) {
-            aca[u].nxt[ch] = aca.size();
-            node n; n.p = u; n.pc = ch; n.depth = i;
-            aca.push_back(n);
-        }
-        u = aca[u].nxt[ch];
+  int u = 0;
+  for (int i = 0; i < ne.size(); i++) {
+    int ch = to_i(ne[i]);
+    if (aca[u].nxt[ch] == -1) {
+      aca[u].nxt[ch] = aca.size();
+      node n; n.p = u; n.pc = ch; n.depth = i;
+      aca.push_back(n);
     }
-    aca[u].leaf = true;
-    aca[u].ix.push_back(ix);
+    u = aca[u].nxt[ch];
+  }
+  aca[u].leaf = true;
+  aca[u].ix.push_back(ix);
 }
 
 int go(int u, int c);
 
 int link(int u) {
-    if (aca[u].lnk != -1) { return aca[u].lnk; }
-    if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; }
-    return aca[u].lnk = go(link(aca[u].p), aca[u].pc);
+  if (aca[u].lnk != -1) { return aca[u].lnk; }
+  if (u == 0 || aca[u].p == 0) { return aca[u].lnk = 0; }
+  return aca[u].lnk = go(link(aca[u].p), aca[u].pc);
 }
 
 int go(int u, int c) {
-    if (aca[u].go[c] != -1) { return aca[u].go[c]; }
-    if (aca[u].nxt[c] != -1)
-        return aca[u].go[c] = aca[u].nxt[c];
-    if (u == 0) { return aca[u].go[c] = 0; }
-    return aca[u].go[c] = go(link(u), c);
+  if (aca[u].go[c] != -1) { return aca[u].go[c]; }
+  if (aca[u].nxt[c] != -1)
+    return aca[u].go[c] = aca[u].nxt[c];
+  if (u == 0) { return aca[u].go[c] = 0; }
+  return aca[u].go[c] = go(link(u), c);
 }
 
 int out(int u) {
-    if (aca[u].out != -1) { return aca[u].out; }
-    int v = link(u);
-    if (v == 0 || aca[v].leaf) { return aca[u].out = v; }
-    return aca[u].out = out(v);
+  if (aca[u].out != -1) { return aca[u].out; }
+  int v = link(u);
+  if (v == 0 || aca[v].leaf) { return aca[u].out = v; }
+  return aca[u].out = out(v);
 }
 
 vector<int> occ (N); vector<vector<int>> occix (N);
 void process(string hay) {
-    int u = 0;
-    for (int i = 0; i < hay.size(); i++) {
-        int ch = to_i(hay[i]);
-        u = go(u, ch);
-        for (int v = u; v != 0; v = out(v)) {
-            for (auto ix : aca[v].ix)
-                // match at (i - aca[v].depth), O(len + ans)
-                occix[ix].push_back(i - aca[v].depth);
-            aca[v].occ++;
-        }
+  int u = 0;
+  for (int i = 0; i < hay.size(); i++) {
+    int ch = to_i(hay[i]);
+    u = go(u, ch);
+    for (int v = u; v != 0; v = out(v)) {
+      for (auto ix : aca[v].ix)
+        // match at (i - aca[v].depth), O(len + ans)
+        occix[ix].push_back(i - aca[v].depth);
+      aca[v].occ++;
     }
-    for (int u = 0; u < aca.size(); u++)
-        for (auto ix : aca[u].ix)
-            // number of matches, O(len)
-            occ[ix] += aca[u].occ;
+  }
+  for (int u = 0; u < aca.size(); u++)
+    for (auto ix : aca[u].ix)
+      // number of matches, O(len)
+      occ[ix] += aca[u].occ;
 }
diff --git a/fontes/bellman-ford.cpp b/fontes/bellman-ford.cpp
deleted file mode 100644
index ce1267b22b20c9b1d2c90e8b8d885dd5afcfffc9..0000000000000000000000000000000000000000
--- a/fontes/bellman-ford.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-struct edge { int u, v, w; };
-vector<edge> edges;
-vi dist (N);
-
-int bellman_ford (int source, int destination, int N) {
-  fill(dist.begin(), dist.begin() + N, oo);
-  dist[source] = 0;
-
-  for (int i = 0; i < N; i++)
-    for (auto e : edges)
-      if (dist[e.u] != oo &&
-          dist[e.v] > dist[e.u] + e.w)
-        dist[e.v] = dist[e.u] + e.w;
-
-  // Verificação de ciclos negativos
-  for (auto e : edges)
-    if (dist[e.u] != oo &&
-        dist[e.v] > dist[e.u] + e.w)
-      return -oo;
-
-  return dist[destination];
-}
diff --git a/fontes/bellman-ford.h b/fontes/bellman-ford.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a95d6ecd05acb6aa40bfa66d79e5aa92e100aeb
--- /dev/null
+++ b/fontes/bellman-ford.h
@@ -0,0 +1,16 @@
+struct edge { int u, v, w; };
+vector<edge> edges;
+vector<int> d (N, oo);
+
+int bellman_ford(int src, int dest, int n) {
+    d[src] = 0;
+    for (int i = 0; i < n - 1; i++)
+    for (auto e : edges)
+        if (d[e.u] != oo && d[e.v] > d[e.u] + e.w)
+            d[e.v] = d[e.u] + e.w;
+    // Verificação de ciclos negativos
+    for (auto e : edges)
+        if (d[e.u] != oo && d[e.v] > d[e.u] + e.w)
+            return -oo;
+    return d[dest];
+}
diff --git a/fontes/bfs.h b/fontes/bfs.h
index 97c924bb8cc97d5cbb593facfa1d5f49ac7476b7..a0dc89005601344db7fc6e4c57382a69982ce3ce 100644
--- a/fontes/bfs.h
+++ b/fontes/bfs.h
@@ -1,14 +1,14 @@
 int explore(int u) {
-    int c = 0;
-    queue<int> q;
-    q.push(u);
-    while (!q.empty()) {
-        int u = q.front(); q.pop();
-        for (int v : g[u]) if (!visited[v]) {
-            c++;
-            visited[v] = true;
-            q.push(v);
-        }
+  int c = 0;
+  queue<int> q;
+  q.push(u);
+  while (!q.empty()) {
+    int u = q.front(); q.pop();
+    for (int v : g[u]) if (!visited[v]) {
+      c++;
+      visited[v] = true;
+      q.push(v);
     }
-    return c;
+  }
+  return c;
 }
diff --git a/fontes/bfs01.h b/fontes/bfs01.h
index ccb136133291fc23fc7e8f9bb9fe413ba60b40cd..cc1cac54d02ee9243d1aee71c57844bc20f25aab 100644
--- a/fontes/bfs01.h
+++ b/fontes/bfs01.h
@@ -1,20 +1,20 @@
 vector<int> d (N, oo);
 
 void bfs01(int s) {
-    d[s] = 0;
-    deque<int> q;
-    q.push_front(s);
-    while (!q.empty()) {
-        int u = q.front();
-        q.pop_front();
-        for (auto [v, w] : g[u]) {
-            if (d[u] + w < d[v]) {
-                d[v] = d[u] + w;
-                if (w == 1)
-                    q.push_back(v);
-                else
-                    q.push_front(v);
-            }
-        }
+  d[s] = 0;
+  deque<int> q;
+  q.push_front(s);
+  while (!q.empty()) {
+    int u = q.front();
+    q.pop_front();
+    for (auto [v, w] : g[u]) {
+      if (d[u] + w < d[v]) {
+        d[v] = d[u] + w;
+        if (w == 1)
+          q.push_back(v);
+        else
+          q.push_front(v);
+      }
     }
+  }
 }
diff --git a/fontes/bigpsieve.h b/fontes/bigpsieve.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f70a53494b1f564db9636599b039a7e15e0e76b
--- /dev/null
+++ b/fontes/bigpsieve.h
@@ -0,0 +1,8 @@
+vector<int> big (N+1, 1);
+
+void biggest_prime_divisor(int n) {
+  for (int i = 1; i <= n; ++i)
+    if (big[i] == 1)
+      for (int j = i; j <= n; j += i)
+        big[j] = i;
+}
diff --git a/fontes/binary-lifting.cpp b/fontes/binary-lifting.cpp
deleted file mode 100644
index 7b2579bfd181dd9a1d8ac4366885a60edd4a65ae..0000000000000000000000000000000000000000
--- a/fontes/binary-lifting.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-const int L = log2(N);
-vector<int> depth (N, 0);
-vector<int> wsum (N);
-vector<vector<int>> weight (N, vector<int>(L+1));
-vector<vector<int>> up (N, vector<int>(L+1));
-
-void bl_euler_tour (int u, int p, int w) {
-  up[u][0] = p;
-  weight[u][0] = w;
-  wsum[u] = wsum[p] + w;
-  depth[u] = depth[p] + 1;
-  for (auto e : graph[u]) if (e.vv != p)
-    bl_euler_tour(e.vv, u, e.ww);
-}
-
-void bl_init (int u) {
-  depth[u] = 0;
-  bl_euler_tour(u, u, 0);
-
-  // can be put into bl_euler_tour
-  // but will not work with cycles then
-  // (but could be useful for online)
-  for (int l = 0; l < L; l++) {
-    for (int u = 0; u < n; u++) {
-      int a = up[u][l];
-      up[u][l+1] = up[a][l];
-      weight[u][l+1] = max(weight[u][l], weight[a][l]);
-    }
-  }
-}
-
-// also bl_lca, just return lca and exclude res
-int bl_query_path (int a, int b) {
-  // if b is deeper than a, swap
-  if (depth[b] > depth[a]) { swap(a, b); }
-
-  int res = 0;
-
-  int diff = depth[a] - depth[b];
-  for (int l = L; l >= 0; d--) if (diff & (1 << l)) {
-    res = max(res, weight[a][l]);
-    a = up[a][l];
-  }
-
-  if (a == b) { /* lca == a */ return res; }
-
-  for (int l = L; l >= 0; d--)
-    if (up[a][l] != up[b][l]) {
-      res = max({ res, weight[a][l], weight[b][l] });
-      a = up[a][l], b = up[b][l];
-    }
-
-  // lca == up[a][0]
-  return max({ res, weight[a][0], weight[b][0] });
-}
-
-int bl_get_one_down (int a, int b) {
-  // if b is deeper than a, swap
-  if (depth[b] > depth[a]) { swap(a, b); }
-
-  int diff = max(depth[a] - depth[b] - 1, 0);
-  for (int l = L; l >= 0; d--) if (diff & (1 << l)) {
-    a = up[a][l];
-  }
-
-  return a;
-}
-
-int bl_query_sum (int a, int b) {
-  int lca = bl_lca(a, b);
-  return (wsum[a] - wsum[lca]) + (wsum[b] - wsum[lca]);
-}
diff --git a/fontes/bl.h b/fontes/bl.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8f2093beb90b28074202e5af9ac54ce7dc82024
--- /dev/null
+++ b/fontes/bl.h
@@ -0,0 +1,44 @@
+const int L = log2(N);
+vector<int> dep (N, 0); vector<ll> wsum (N);
+vector<vector<ll>> weiop (N, vector<ll>(L+1));
+vector<vector<int>> up (N, vector<int>(L+1));
+
+void bl_euler_tour(int u, int p, int w) {
+  up[u][0] = p; weiop[u][0] = w;
+  dep[u] = dep[p] + 1; wsum[u] = wsum[p] + w;
+  for (auto [v, w] : g[u]) if (v != p)
+    bl_euler_tour(v, u, w);
+}
+
+void bl_init(int u, int n) {
+  dep[u] = 0; bl_euler_tour(u, u, 0);
+  // can be put into bl_euler_tour but it will not
+  // work with cycles (could be useful for online)
+  for (int l = 0; l < L; l++)
+    for (int u = 0; u < n; u++) {
+      int a = up[u][l];
+      up[u][l+1] = up[a][l];
+      weiop[u][l+1] = OP(weiop[u][l], weiop[a][l]);
+    }
+}
+
+ll bl_op(int a, int b) {
+  if (!(dep[a] > dep[b])) { swap(a, b); }
+  ll res = NEUTRAL;
+  int diff = dep[a] - dep[b];
+  for (int l = L; l >= 0; l--) if (diff & (1 << l)) {
+    res = OP(res, weiop[a][l]); a = up[a][l];
+  }
+  if (a == b) { return res; }
+  for (int l = L; l >= 0; l--)
+    if (up[a][l] != up[b][l]) {
+      res = OP(res, OP(weiop[a][l], weiop[b][l]));
+      a = up[a][l], b = up[b][l];
+    }
+  return OP(res, OP(weiop[a][0], weiop[b][0]));
+}
+
+int bl_query_sum(int a, int b) {
+  int lca = bl_lca(a, b);
+  return (wsum[a] - wsum[lca]) + (wsum[b] - wsum[lca]);
+}
diff --git a/fontes/bllca.h b/fontes/bllca.h
index 4bcd8b2e9966c3c319b5c500617103e7b0f88c14..6e450e45b167ca6cff508dc165a6428ebdc772c8 100644
--- a/fontes/bllca.h
+++ b/fontes/bllca.h
@@ -1,10 +1,18 @@
 int bl_lca(int a, int b) {
-    if (!(depth[b] < depth[a])) { swap(a, b); }
-    int diff = depth[a] - depth[b];
-    for (int l = L; l >= 0; l--) if (diff & (1 << l))
-        a = up[a][l];
-    if (a == b) { return a; }
-    for (int l = L; l >= 0; l--) if (up[a][l] != up[b][l])
-        a = up[a][l], b = up[b][l];
-    return up[a][0];
+  if (!(dep[b] < dep[a])) { swap(a, b); }
+  int diff = dep[a] - dep[b];
+  for (int l = L; l >= 0; l--) if (diff & (1 << l))
+    a = up[a][l];
+  if (a == b) { return a; }
+  for (int l = L; l >= 0; l--) if (up[a][l] != up[b][l])
+    a = up[a][l], b = up[b][l];
+  return up[a][0];
+}
+
+int bl_get_one_down(int a, int b) {
+  if (!(dep[b] < dep[a])) { swap(a, b); }
+  int diff = max(dep[a] - dep[b] - 1, 0);
+  for (int l = L; l >= 0; d--) if (diff & (1 << l))
+    a = up[a][l];
+  return a;
 }
diff --git a/fontes/connected.cpp b/fontes/connected.cpp
deleted file mode 100644
index 69913816958316b5a8a2f808b8a30e26644f412b..0000000000000000000000000000000000000000
--- a/fontes/connected.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-bool check_graph_connected_dfs() {
-  int start_vertex = 0;
-  visited = vector<int>(n_vertices, false);
-  dfs(start_vertex);
-  return (find(all(visited), 0) == visited.end());
-}
-
-bool check_graph_connected_bfs() {
-  int start_vertex = 0;
-  vector<int> visited(n_vertices, false);
-  queue<int> Q;
-  Q.push(start_vertex);
-  visited[start_vertex] = true;
-
-  while (!Q.empty()) {
-    int i = Q.front();
-    Q.pop();
-
-    for (auto node : graph[i]) {
-      if (!visited[node]) {
-        visited[node] = true;
-        Q.push(node);
-      }
-    }
-  }
-
-  return find(all(visited), 0) == visited.end();
-}
diff --git a/fontes/dfsrec.h b/fontes/dfsrec.h
index 04b2dde8d72ce281d6fda4336e2d19bb21d1628d..ab58fc212d58219c10b57ba37c155ce42f6dd228 100644
--- a/fontes/dfsrec.h
+++ b/fontes/dfsrec.h
@@ -1,7 +1,7 @@
 int explore(int u) {
-    visited[u] = true;
-    int c = 1;
-    for (int v : g[u]) if (!visited[v])
-        c += explore(v);
-    return c;
+  visited[u] = true;
+  int c = 1;
+  for (int v : g[u]) if (!visited[v])
+    c += explore(v);
+  return c;
 }
diff --git a/fontes/dfsstack.h b/fontes/dfsstack.h
index 3b8e6be2b217a36f1beb502b127b3b864ea1f73e..95d045893ccc4c6631d16608b59289a3abeb0dcb 100644
--- a/fontes/dfsstack.h
+++ b/fontes/dfsstack.h
@@ -1,14 +1,14 @@
 int explore(int u) {
-    int c = 0;
-    stack<int> s;
-    s.push(u);
-    while (!s.empty()) {
-        int u = s.top(); s.pop();
-        for (int v : g[u]) if (!visited[v]) {
-            c++;
-            visited[v] = true;
-            s.push(v);
-        }
+  int c = 0;
+  stack<int> s;
+  s.push(u);
+  while (!s.empty()) {
+    int u = s.top(); s.pop();
+    for (int v : g[u]) if (!visited[v]) {
+      c++;
+      visited[v] = true;
+      s.push(v);
     }
-    return c;
+  }
+  return c;
 }
diff --git a/fontes/dijkstra.h b/fontes/dijkstra.h
index e70b8f22ee579ddb6994faf26b09f92777958520..8ebebe1849a2bad3315b26481fd0909661e56569 100644
--- a/fontes/dijkstra.h
+++ b/fontes/dijkstra.h
@@ -1,5 +1,6 @@
 vector<ll> d (N); vector<bool> vis (N);
 vector<vector<int>> dag (N);
+
 void dijkstra(int src, int dest) {
   fill(d.begin(), d.end(), oo);
   fill(vis.begin(), vis.end(), false);
diff --git a/fontes/divisors.h b/fontes/divisors.h
new file mode 100644
index 0000000000000000000000000000000000000000..45d4ed83f1d2a0dae39a3f6941f41998daea2e4f
--- /dev/null
+++ b/fontes/divisors.h
@@ -0,0 +1,6 @@
+vector<int> divisors (N);
+void number_of_divisors(int n) {
+  for (int i = 1; i <= n; ++i)
+    for (int j = i; j <= n; j += i)
+      divisors[j]++;
+}
diff --git a/fontes/euler-totient.h b/fontes/euler-totient.h
index 0563c7a0990e227db3b29d7888b40059c757d477..a0368fcab385e3e93cb4683bb76e991bc8c5cc72 100644
--- a/fontes/euler-totient.h
+++ b/fontes/euler-totient.h
@@ -1,6 +1,5 @@
 vector<ll> phi (N);
 
-// O(n lg lg n)
 void totient(int n) {
   for (int i = 1; i <= n; i++) { phi[i] = i; }
   for (int i = 2; i <= n; i++) if (phi[i] == i) {
diff --git a/fontes/ffek.h b/fontes/ffek.h
new file mode 100644
index 0000000000000000000000000000000000000000..1131688cd9aae1f4cb8c5cb038ffc211cac0ae6a
--- /dev/null
+++ b/fontes/ffek.h
@@ -0,0 +1,44 @@
+vector<vector<int>> res (N);
+vector<int> ix (N), dist (N), par (N);
+struct edge { int u, v, cap; };
+vector<edge> edges;
+
+void link(int u, int v, int c) {
+  res[u].pb(edges.size()); edges.pb({ u, v, c });
+  res[v].pb(edges.size()); edges.pb({ v, u, 0 });
+}
+
+bool minimum_path(int s, int t) {
+  fill(dist.begin(), dist.end(), oo); dist[s] = 0;
+  queue<int> q; q.push(s);
+  while (!q.empty()) {
+    int u = q.front(); q.pop();
+    if (u == t) { break; }
+    for (int i : res[u]) {
+      edge e = edges[i]; int v = e.v;
+      if (e.cap && dist[v] == oo) {
+        dist[v] = dist[u] + 1;
+        par[v] = u; ix[v] = i;
+        q.push(v);
+      }
+    }
+  }
+  return dist[t] < oo;
+}
+
+pair<int, int> ffek(int s, int t) {
+  int min_cost = 0, max_flow = 0;
+  while (minimum_path(s, t)) {
+    int flow = oo;
+    for (int u = t; u != s; u = par[u]) {
+      flow = min(flow, edges[ix[u]].cap);
+    }
+    for (int u = t; u != s; u = par[u]) {
+      edges[ix[u]  ].cap -= flow;
+      edges[ix[u]^1].cap += flow;
+    }
+    min_cost += flow * dist[t];
+    max_flow += flow;
+  }
+  return { min_cost, max_flow };
+}
diff --git a/fontes/ffekbfs.h b/fontes/ffekbfs.h
deleted file mode 100644
index 56fcaa22ba0d06b68d9706b099399c8e1ddffa35..0000000000000000000000000000000000000000
--- a/fontes/ffekbfs.h
+++ /dev/null
@@ -1,18 +0,0 @@
-vector<int> ix (N), dist (N), par (N);
-bool minimum_path(int s, int t) {
-  fill(dist.begin(), dist.end(), oo); dist[s] = 0;
-  queue<int> q; q.push(s);
-  while (!q.empty()) {
-    int u = q.front(); q.pop();
-    if (u == t) { break; }
-    for (int i : res[u]) {
-      edge e = edges[i]; int v = e.v;
-      if (e.cap && dist[v] == oo) {
-        dist[v] = dist[u] + 1;
-        par[v] = u; ix[v] = i;
-        q.push(v);
-      }
-    }
-  }
-  return dist[t] < oo;
-}
diff --git a/fontes/ffekmincost.h b/fontes/ffekmincost.h
new file mode 100644
index 0000000000000000000000000000000000000000..5490dd1d042e2b0cff38cd7a994e3c7719a2f639
--- /dev/null
+++ b/fontes/ffekmincost.h
@@ -0,0 +1,29 @@
+struct edge { int u, v, cap, cost; };
+vector<edge> edges;
+
+vector<int> queu (N), ix (N), dist (N), par (N);
+
+void link(int u, int v, int cap, int cost) {
+  res[u].push_back(edges.size());
+  edges.push_back({ u, v, cap, cost });
+  res[v].push_back(edges.size());
+  edges.push_back({ v, u, 0, -cost });
+}
+
+bool minimum_path(int s, int t) {
+  fill(dist.begin(), dist.end(), oo); dist[s] = 0;
+  queue<int> q; q.push(s);
+  while (!q.empty()) {
+    int u = q.front(); q.pop();
+    queu[u] = 0;
+    for (int i : res[u]) {
+      edge e = edges[i]; int v = e.v;
+      if (e.cap && dist[v] > dist[u] + e.cost) {
+        dist[v] = dist[u] + e.cost;
+        par[v] = u; ix[v] = i;
+        if (!queu[v]) { q.push(v); queu[v] = 1; }
+      }
+    }
+  }
+  return dist[t] < oo;
+}
diff --git a/fontes/ffekspfa.h b/fontes/ffekspfa.h
deleted file mode 100644
index 1d6a97b4326042f8c88cdc8a76f5817dd192c827..0000000000000000000000000000000000000000
--- a/fontes/ffekspfa.h
+++ /dev/null
@@ -1,18 +0,0 @@
-vector<int> queu (N), ix (N), dist (N), par (N);
-bool minimum_path(int s, int t) {
-    fill(dist.begin(), dist.end(), oo); dist[s] = 0;
-    queue<int> q; q.push(s);
-    while (!q.empty()) {
-        int u = q.front(); q.pop();
-        queu[u] = 0;
-        for (int i : res[u]) {
-            edge e = edges[i]; int v = e.v;
-            if (e.cap && dist[v] > dist[u] + e.cost) {
-                dist[v] = dist[u] + e.cost;
-                par[v] = u; ix[v] = i;
-                if (!queu[v]) { q.push(v); queu[v] = 1; }
-            }
-        }
-    }
-    return dist[t] < oo;
-}
diff --git a/fontes/floyd-warshall.cpp b/fontes/floyd-warshall.cpp
deleted file mode 100644
index a120f43f8296d86a51d39b0cc39f31ddd161251c..0000000000000000000000000000000000000000
--- a/fontes/floyd-warshall.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-for (int k = 0; k < N; k++)
-for (int i = 0; i < N; i++)
-for (int j = 0; j < N; j++)
-  dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
diff --git a/fontes/floyd-warshall.h b/fontes/floyd-warshall.h
new file mode 100644
index 0000000000000000000000000000000000000000..510f550260ebf915fc71051dd5fb0b8905f104dc
--- /dev/null
+++ b/fontes/floyd-warshall.h
@@ -0,0 +1,10 @@
+vector<vector<ll>> d (N, vector<ll>(N, oo));
+
+int floydwarshall(int n) {
+  for (int u = 0; u < n; u++)
+    d[u][u] = 0;
+  for (int m = 0; m < n; m++)
+    for (int u = 0; u < n; u++)
+      for (int v = 0; v < n; v++)
+        d[u][v] = min(d[u][v], d[u][m] + d[m][v]);
+}
diff --git a/fontes/hld.h b/fontes/hld.h
index b9fe87274900b617fa724fdef0171bb01451354f..9febdd92b860fe5ed324a84caa82b5d7a7eeb9fe 100644
--- a/fontes/hld.h
+++ b/fontes/hld.h
@@ -14,9 +14,7 @@ int hld_fill(int u, int p, int d = 0, ll w = 0) {
 }
 
 void hld(int u, int h) {
-  hds[u] = h;
-  ori[cix] = wei[u];
-  ixs[u] = cix++;
+  hds[u] = h; ori[cix] = wei[u]; ixs[u] = cix++;
   if (hvy[u] != -1)
     hld(hvy[u], h); // continue chain
   for (auto [v, w] : g[u]) if (v != par[u] && v != hvy[u])
@@ -27,8 +25,7 @@ ll hld_op(int u, int v, bool edge_wei = 1) {
   ll ans = 0;
   for (; hds[u] != hds[v]; v = par[hds[v]]) {
     if (dep[hds[u]] > dep[hds[v]]) { swap(u, v); }
-    ans = OP(ans,
-        op_inclusive(ixs[hds[v]], ixs[v]));
+    ans = OP(ans, op_inclusive(ixs[hds[v]], ixs[v]));
   }
   if (dep[u] > dep[v]) { swap(u, v); }
   return OP(ans, op_inclusive(ixs[u] + edge_wei, ixs[v]));
diff --git a/fontes/hopcroft.h b/fontes/hopcroft.h
new file mode 100644
index 0000000000000000000000000000000000000000..ff08c1c758ef5dce60764032473bbf4e1c0b3eb5
--- /dev/null
+++ b/fontes/hopcroft.h
@@ -0,0 +1,40 @@
+vector<int> matchl (L, -1), matchr (R, -1);
+vector<int> dist (L);
+
+bool bfs(int l) {
+  queue<int> Q;
+  for (int l = 0; l < L; l++)
+    if (matchl[l] == -1) { dist[l] = 0; Q.push(l); }
+    else { dist[l] = -1; }
+  bool ans = false;
+  while (!Q.empty()) {
+    int l = Q.front(); Q.pop();
+    for (auto r : g[l])
+      if (matchr[r] == -1) {
+        ans = true;
+      } else if (dist[matchr[r]] == -1) {
+        dist[matchr[r]] = dist[l] + 1;
+        Q.push(matchr[r]);
+      }
+  }
+  return ans;
+}
+
+bool dfs(int l) {
+  if (l == -1) { return true; }
+  for (auto r : g[l])
+    if (matchr[r] == -1 || dist[matchr[r]] == dist[l] + 1)
+      if (dfs(matchr[r])) {
+        matchr[r] = l;
+        matchl[l] = r;
+        return true;
+      }
+  return false;
+}
+
+int hopcroft(int l) {
+  int ans = 0;
+  while (bfs(l)) for (int u = 0; u < l; u++)
+    if (matchl[u] == -1 && dfs(u)) { ans++; }
+  return ans;
+}
diff --git a/fontes/kmp.h b/fontes/kmp.h
index e47fbce076a37dff55479d39be61893dcc48cfd5..43b41368ebf03cc3ed6ba90b715bf47d248365f4 100644
--- a/fontes/kmp.h
+++ b/fontes/kmp.h
@@ -1,25 +1,25 @@
 vector<int> pre(string ne) {
-    int n = ne.size();
-    vector<int> pi (n, 0);
-    for (int i = 1, j = 0; i < n; i++) {
-        while (j > 0 && ne[i] != ne[j]) { j = pi[j-1]; }
-        if (ne[i] == ne[j]) { j++; }
-        pi[i] = j;
-    }
-    return pi;
+  int n = ne.size();
+  vector<int> pi (n, 0);
+  for (int i = 1, j = 0; i < n; i++) {
+    while (j > 0 && ne[i] != ne[j]) { j = pi[j-1]; }
+    if (ne[i] == ne[j]) { j++; }
+    pi[i] = j;
+  }
+  return pi;
 }
 
 int search(string hay, string ne) {
-    vector<int> pi = pre(ne);
-    int c = 0;
-    for (int i = 0, j = 0; i < hay.size(); i++) {
-        while (j > 0 && hay[i] != ne[j]) { j = pi[j-1]; }
-        if (hay[i] == ne[j]) { j++; }
-        if (j == ne.size()) {
-            c++;
-            // match at (i-j+1)
-            j = pi[j-1];
-        }
+  vector<int> pi = pre(ne);
+  int c = 0;
+  for (int i = 0, j = 0; i < hay.size(); i++) {
+    while (j > 0 && hay[i] != ne[j]) { j = pi[j-1]; }
+    if (hay[i] == ne[j]) { j++; }
+    if (j == ne.size()) {
+      c++;
+      // match at (i-j+1)
+      j = pi[j-1];
     }
-    return c;
+  }
+  return c;
 }
diff --git a/fontes/kosaraju.cpp b/fontes/kosaraju.cpp
deleted file mode 100644
index c23654f69aef8a803e95e7a4368e3052e2bd260d..0000000000000000000000000000000000000000
--- a/fontes/kosaraju.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-int timestamp = 0;
-vector<int> visited (N);
-vector<vector<int>> G (N);
-vector<vector<int>> G_t (N);
-vector<int> rep (N);
-stack<int> S;
-
-void fill_stack (int u) {
-  visited[u] = timestamp;
-  for (int v : G[u]) if (visited[v] != timestamp) {
-    fill_stack(v);
-  }
-  S.push(u);
-}
-
-void mark_component (int u, int my_rep) {
-  visited[u] = timestamp;
-  rep[u] = my_rep;
-  for (int v : G_t[u]) if (visited[v] != timestamp) {
-    mark_component(v, my_rep);
-  }
-}
-
-vector<int> kosaraju (int n) {
-  timestamp++;
-  for (int u = 0; u < n; u++) if (visited[u] != timestamp) {
-    fill_stack(u);
-  }
-
-  timestamp++;
-  vector<int> topo_components;
-  while (!S.empty()) {
-    int u = S.top(); S.pop();
-    if (visited[u] != timestamp) {
-      mark_component(u, u);
-      topo_components.push_back(u);
-    }
-  }
-
-  return topo_components;
-}
diff --git a/fontes/kosaraju.h b/fontes/kosaraju.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ca7baa46fff70760f555cb702a22d554a81f2b4
--- /dev/null
+++ b/fontes/kosaraju.h
@@ -0,0 +1,28 @@
+int cts = 1;
+vector<int> vis (N), rep (N);
+stack<int> sinks;
+
+void fill_stack(int u) {
+    if (vis[u] == cts) { return; }
+    vis[u] = cts;
+    for (int v : g_t[u]) { fill_stack(v); }
+    sinks.push(u);
+}
+
+void mark_component(int u, int r) {
+    if (vis[u] == cts) { return; }
+    vis[u] = cts; rep[u] = r;
+    for (int v : g[u]) { mark_component(v, r); }
+}
+
+stack<int> kosaraju(int n) {
+    for (int u = 0; u < n; u++) { fill_stack(u); }
+    cts++;
+    stack<int> topo;
+    while (!sinks.empty()) {
+        int u = sinks.top(); sinks.pop();
+        mark_component(u, u);
+        if (rep[u] == u) topo.push(u);
+    }
+    return topo;
+}
diff --git a/fontes/kuhn.h b/fontes/kuhn.h
new file mode 100644
index 0000000000000000000000000000000000000000..07e43a93cf9c28694d10adef89d4a2ba43b2423e
--- /dev/null
+++ b/fontes/kuhn.h
@@ -0,0 +1,19 @@
+// u e v são enumerações distintas (podem repetir)
+vector<vector<int>> g (L);
+vector<int> matchr (R, -1);
+
+int dfs(int u) {
+  if (vis[u] == cts) { return 0; }
+  vis[u] = cts;
+  for (int v : g[u])
+    if (matchr[v] == -1 || dfs(matchr[v])) {
+      matchr[v] = u; return 1;
+    }
+  return 0;
+}
+
+int kuhn(int l) {
+  int ans = 0;
+  for (int u = 0; u < l; u++) { ans += dfs(u); cts++; }
+  return ans;
+}
diff --git a/fontes/linearsieve.h b/fontes/linearsieve.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f69a1d399c6869a10f660ac620e3af8583a2f7d
--- /dev/null
+++ b/fontes/linearsieve.h
@@ -0,0 +1,9 @@
+vector<int> pr, lp (1e7+15);
+void eulersieve(int n) {
+  for (int i = 2; i <= n; i++) {
+    if (lp[i] == 0) { lp[i] = i; pr.push_back(i); }
+    for (int j = 0; j < int(pr.size())
+        && pr[j] <= lp[i] && i*pr[j] <= n; j++)
+      lp[i * pr[j]] = pr[j];
+  }
+}
diff --git a/fontes/max-flow-ffek.cpp b/fontes/max-flow-ffek.cpp
deleted file mode 100644
index a7ebd9528626c34d074d8919e67b791b231ccb76..0000000000000000000000000000000000000000
--- a/fontes/max-flow-ffek.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Minimum-cost, maximum flow, all costs 1
-// Ford-Fulkerson, Edmonds-Karp implementation
-// Time: O(V^2 * E)
-
-vector<vector<int>> res (3e3+15);
-vector<vector<int>> cap (3e3+15, vector<int>(3e3+15));
-
-vector<int> parent(3e3+15);
-vector<int> dist(3e3+15);
-
-bool bfs(int s, int t) {
-  fill(dist.begin(), dist.end(), oo);
-  dist[s] = 0;
-
-  queue<int> Q;
-  Q.push(s);
-
-  while (!Q.empty()) {
-    int u = Q.front(); Q.pop();
-    if (u == t) { break; }
-    for (int v : res[u]) {
-      if (dist[v] != oo) { continue; }
-      if (cap[u][v] == 0) { continue; }
-      dist[v] = dist[u] + 1;
-      parent[v] = u;
-      Q.push(v);
-    }
-  }
-
-  return dist[t] < oo;
-}
-
-int ffek(int s, int t) {
-  int min_cost = 0;
-  int max_flow = 0;
-  while (bfs(s, t)) {
-    int flow = oo;
-    for (int u = t; u != s; u = parent[u]) {
-      flow = min(flow, cap[parent[u]][u]);
-    }
-    for (int u = t; u != s; u = parent[u]) {
-      cap[parent[u]][u] -= flow;
-      cap[u][parent[u]] += flow;
-    }
-    min_cost += flow * dist[t];
-    max_flow += flow;
-  }
-  return max_flow;
-}
diff --git a/fontes/min-cost-max-flow.cpp b/fontes/min-cost-max-flow.cpp
deleted file mode 100644
index 04f4304ddd2aa9efcb09e85f386dbf83d65bdf4d..0000000000000000000000000000000000000000
--- a/fontes/min-cost-max-flow.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// Minimum-cost, maximum flow, variable cost
-// Ford-Fulkerson, Edmonds-Karp implementation
-// Time: O(V^2 * E)
-
-struct edge { int u, v, cap, cost; };
-vector<edge> edges;
-vector<vector<int>> res (3e3+15);
-
-vector<bool> queued(3e3+15);
-vector<int> parent(3e3+15);
-vector<int> ind(3e3+15);
-vector<int> dist(3e3+15);
-
-void link(int u, int v, int cap, int cost) {
-  res[u].push_back(edges.size());
-  edges.push_back({ u, v, cap, cost });
-  res[v].push_back(edges.size());
-  edges.push_back({ v, u, 0, -cost });
-}
-
-bool spfa(int s, int t) {
-  fill(dist.begin(), dist.end(), oo);
-  fill(queued.begin(), queued.end(), false);
-  dist[s] = 0;
-
-  queue<int> Q;
-  Q.push(s);
-
-  while (!Q.empty()) {
-    int u = Q.front(); Q.pop();
-    if (u == t) { break; }
-    queued[u] = false;
-
-    for (int i : res[u]) {
-      edge e = edges[i];
-      int v = e.v;
-      if (e.cap && dist[v] > dist[u] + e.cost) {
-        dist[v] = dist[u] + e.cost;
-        parent[v] = u;
-        ind[v] = i;
-        if (!queued[v]) {
-          Q.push(v);
-          queued[v] = true;
-        }
-      }
-    }
-  }
-
-  return dist[t] < oo;
-}
-
-pair<int, int> ffek(int s, int t) {
-  int min_cost = 0;
-  int max_flow = 0;
-  while (spfa(s, t)) {
-    int flow = oo;
-    for (int u = t; u != s; u = parent[u]) {
-      flow = min(flow, edges[ind[u]].cap);
-    }
-    for (int u = t; u != s; u = parent[u]) {
-      edges[ind[u]  ].cap -= flow;
-      edges[ind[u]^1].cap += flow;
-    }
-    min_cost += flow * dist[t];
-    max_flow += flow;
-  }
-  return {min_cost, max_flow};
-}
diff --git a/fontes/numbers.h b/fontes/numbers.h
index 0f4558ad979740b4aa5436df08047e510933493b..7dc33543514394535fc02d57fbd26dbe4b763f45 100644
--- a/fontes/numbers.h
+++ b/fontes/numbers.h
@@ -6,3 +6,4 @@ ll equals_zero_mod_m_inclusive(ll a, ll b, ll m) {
 ll multiples_inclusive(ll a, ll b, ll x) {
     return b/x - (a-1)/x; }
 ll ceil_div(ll x, ll y) { return (x/y) + bool(x%y); }
+ll round_div(ll x, ll y) { return (x+y/2)/y; }
diff --git a/fontes/point.h b/fontes/point.h
index 822a380c0005b5d9c0fbe22559989377f623dc20..968b9802ba7f587ce3b1e92c3513ed7a185bd75a 100644
--- a/fontes/point.h
+++ b/fontes/point.h
@@ -7,10 +7,13 @@ pt vec(pt a, pt b) { return b - a; }
 int sgn(double v) { return (v > -EPS) - (v < EPS); }
 // -1 (cw), 0 (colinear), +1 (ccw)
 int seg_ornt(pt a, pt b, pt c) {
-    return sgn(cross(vec(a, b), vec(a, c))); }
+  return sgn(cross(vec(a, b), vec(a, c)));
+}
 int ccw(pt a, pt b, pt c, bool col) {
-    int o = seg_ornt(a, b, c);
-    return (o == 1) || (o == 0 && col); }
+  int o = seg_ornt(a, b, c);
+  return (o == 1) || (o == 0 && col);
+}
 const double PI = acos(-1);
 double angle(pt a, pt b, pt c) {
-    return abs(remainder(arg(a-b) - arg(c-b), 2.0 * PI)); }
+  return abs(remainder(arg(a-b) - arg(c-b), 2.0 * PI));
+}
diff --git a/fontes/prim.h b/fontes/prim.h
index 666a8f4ebce89e0176e7c23765d01b415d0209fe..7c8431a28340e7315f6ff3cc300878c0dc514f52 100644
--- a/fontes/prim.h
+++ b/fontes/prim.h
@@ -2,6 +2,7 @@ vector<bool> vis (N);
 vector<int> par (N, -1);
 vector<ll> d (N, oo);
 vector<vector<ii>> pt (N);
+
 ll prim(int src) {
   ll sum = 0;
   priority_queue<ii, vector<ii>, greater<ii>> Q;
diff --git a/fontes/rabinkarp.h b/fontes/rabinkarp.h
index c725ee9349429ec2f71850775d66c04c2184af83..f6ed7f74c75439e0dd3182305ca0b95981ccb8bf 100644
--- a/fontes/rabinkarp.h
+++ b/fontes/rabinkarp.h
@@ -1,20 +1,20 @@
 const int P = 31; const int M = 1e9 + 9;
 int search(string hay, string ne) {
-    int n = hay.size(), m = ne.size();
-    vector<ll> ps (max(n, m), 1);
-    for (int i = 1; i < max(n, m); i++)
-        ps[i] = (ps[i-1] * P) % M;
-    vector<ll> h (n+1, 0);
-    for (int i = 0; i < n; i++)
-        h[i+1] = (h[i] + (hay[i]-'a'+1) * ps[i]) % M;
-    ll hne = 0;
-    for (int i = 0; i < m; i++)
-        hne = (hne + (ne[i]-'a'+1) * ps[i]) % M;
-    int c = 0;
-    for (int i = 0; i < n - m + 1; i++)
-        if ((h[i+m] - h[i] + M) % M == hne * ps[i] % M) {
-            // match at i
-            c++;
-        }
-    return c;
+  int n = hay.size(), m = ne.size();
+  vector<ll> ps (max(n, m), 1);
+  for (int i = 1; i < max(n, m); i++)
+    ps[i] = (ps[i-1] * P) % M;
+  vector<ll> h (n+1, 0);
+  for (int i = 0; i < n; i++)
+    h[i+1] = (h[i] + (hay[i]-'a'+1) * ps[i]) % M;
+  ll hne = 0;
+  for (int i = 0; i < m; i++)
+    hne = (hne + (ne[i]-'a'+1) * ps[i]) % M;
+  int c = 0;
+  for (int i = 0; i < n - m + 1; i++)
+    if ((h[i+m] - h[i] + M) % M == hne * ps[i] % M) {
+      // match at i
+      c++;
+    }
+  return c;
 }
diff --git a/fontes/sieve-of-eratosthenes.cpp b/fontes/sieve-of-eratosthenes.cpp
deleted file mode 100644
index 727f6e30dcbceb629fb486e4cdeca42d681cf541..0000000000000000000000000000000000000000
--- a/fontes/sieve-of-eratosthenes.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-vector<bool> sieve (n + 1, true);
-
-void sieve_eratosthenes /* O (n lg lg n) */ (int n) {
-  for (int i = 2; i * i <= n; i++) if (sieve[i]) {
-    for (int j = i * i; j <= n; j += i) {
-      sieve[j] = false;
-    }
-  }
-}
-
-vector<int> divisors (n + 1);
-
-void number_of_divisors /* O(n lg n) */ (int n) {
-  for (int i = 1; i <= n; ++i)
-    for (int j = i; j <= n; j += i)
-      divisors[j]++;
-}
-
-vector<int> sum_divisors (n + 1);
-
-void sum_of_divisors /* O(n lg n) */ (int n) {
-  for (int i = 1; i <= n; ++i)
-    for (int j = i; j <= n; j += i)
-      sum_divisors[j] += i;
-}
-
-vector<int> totient (n + 1);
-
-void euler_totient /* O(n lg lg n) */ (int n) {
-  for (int i = 1; i <= n; ++i) totient[i] = i;
-  for (int i = 2; i <= n; ++i)
-    if (totient[i] == i)
-      for (int j = i; j <= n; j += i)
-        totient[j] -= totient[j] / i;
-}
-
-vector<int> big (n + 1) = { 1, 1 };
-
-void biggest_prime_divisor /* O(n lg lg n) */ (int n) {
-  for (int i = 1; i <= n; ++i)
-    if (big[i] == 1)
-      for (int j = i; j <= n; j += i)
-        big[j] = i;
-}
-
-vector<int> lp (n + 1);
-vector<int> pr;
-
-void linear_sieve /* O(n) */ (int n) {
-  for (int i = 2; i <= n; i++) {
-    if (lp[i] == 0) {
-      lp[i] = i;
-      pr.push_back(i);
-    }
-    for (int j = 0; j < pr.size() && pr[j] <= lp[i] && i * pr[j] <= n; j++)
-      lp[i * pr[j]] = pr[j];
-  }
-}
diff --git a/fontes/sieve.h b/fontes/sieve.h
new file mode 100644
index 0000000000000000000000000000000000000000..470673b47ec958c0ac5d1d74ddbbca65349cfced
--- /dev/null
+++ b/fontes/sieve.h
@@ -0,0 +1,6 @@
+vector<bool> sieve (1e7+15, true);
+void eratosthenes(int n) {
+  for (int i = 2; i * i <= n; i++) if (sieve[i])
+    for (int j = i * i; j <= n; j += i)
+      sieve[j] = false;
+}
diff --git a/fontes/spfa.h b/fontes/spfa.h
new file mode 100644
index 0000000000000000000000000000000000000000..6baf3c7f793b79fed74810f709f84bf2e470cce6
--- /dev/null
+++ b/fontes/spfa.h
@@ -0,0 +1,27 @@
+vector<ll> d (N); vector<bool> queu (N);
+vector<int> cnt (N);
+
+bool spfa(int src, int n) {
+  fill(d.begin(), d.end(), oo);
+  fill(cnt.begin(), cnt.end(), 0);
+  d[src] = 0;
+  queue<int> q; q.push(src);
+  while (!q.empty()) {
+    int u = q.front(); q.pop();
+    queu[u] = 0;
+    for (auto [v, w] : g[u]) {
+      if (d[v] > d[u] + w) {
+        d[v] = d[u] + w;
+        if (!queu[v]) {
+          q.push(v);
+          queu[v] = 1;
+          cnt[v]++;
+          if (cnt[v] > n)
+            // negative cycle
+            return false;
+        }
+      }
+    }
+  }
+  return true;
+}
diff --git a/fontes/stress.sh b/fontes/stress.sh
index 39e076b036f382ad938e3319a9cd9c7bc9b5ab70..8e01a861828e73071cff997380f073ba3c581b27 100644
--- a/fontes/stress.sh
+++ b/fontes/stress.sh
@@ -2,8 +2,7 @@ for (( I=0; I < 5; I++ )); do
   ./gen $I >a.in
   ./brute <a.in >a.exp
   ./a.out <a.in >a.out
-  diff -u a.exp a.out
-  if [[ $? -ne 0 ]]; then
+  if diff -u a.exp a.out; then : ; else
     echo "--> entrada:"; cat a.in
     echo "--> saída esperada"; cat a.exp
     echo "--> saída obtida"; cat a.out
diff --git a/fontes/sumdivsieve.h b/fontes/sumdivsieve.h
new file mode 100644
index 0000000000000000000000000000000000000000..afd4fa6801650873e8b9160994f97906eb36e529
--- /dev/null
+++ b/fontes/sumdivsieve.h
@@ -0,0 +1,7 @@
+vector<int> sumdiv (N);
+
+void sum_of_divisors(int n) {
+  for (int i = 1; i <= n; ++i)
+    for (int j = i; j <= n; j += i)
+      sumdiv[j] += i;
+}
diff --git a/fontes/tarjan.cpp b/fontes/tarjan.cpp
deleted file mode 100644
index 7dfb4680344c63e50b0cae2199cffd5862e608fc..0000000000000000000000000000000000000000
--- a/fontes/tarjan.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-int timestamp = 0;
-vector<int> id (1e5 + 1);
-vector<int> lowlink (1e5 + 1, oo);
-vector<int> rep (1e5 + 1, 0);
-vector<int> visited (1e5 + 1, 0);
-vector<bool> on_stack (1e5 + 1, false);
-stack<int> topo_components;
-stack<int> S;
-
-int next_id = 0;
-
-void tarjan_dfs (int u) {
-  if (visited[u] == timestamp) { return; }
-  visited[u] = timestamp;
-  S.push(u); on_stack[u] = true;
-  id[u] = lowlink[u] = next_id++;
-
-  for (int v : G[u]) {
-    tarjan_dfs(v);
-    if (on_stack[v]) {
-      lowlink[u] = min(lowlink[u], lowlink[v]);
-    }
-  }
-
-  if (id[u] == lowlink[u]) {
-    int v;
-    do {
-      v = S.top(); S.pop();
-      on_stack[v] = false;
-      lowlink[v] = id[u];
-      rep[v] = u;
-    } while (v != u);
-    topo_components.push(u);
-  }
-}
-
-stack<int> tarjan (int n) {
-  timestamp++;
-  for (int i = 0; i < n; i++) {
-    tarjan_dfs(i);
-  }
-  return topo_components;
-}
diff --git a/fontes/tarjan.h b/fontes/tarjan.h
index 8a16e74bc7087a7d65f650c7a0b8f6db6034eddb..93f6c4cf2be909fc30cd68438a6081610d5d75e4 100644
--- a/fontes/tarjan.h
+++ b/fontes/tarjan.h
@@ -1,20 +1,25 @@
 vector<int> tin (N, -1), lowlnk (N, -1), rep (N);
-stack<int> st;
+stack<int> st, topo;
+int cts = 0;
+
 void dfs_tarjan(int u) {
-    if (tin[u] != -1) { return; }
-    lowlnk[u] = tin[u] = vis[u] = cts++;
-    st.push(u);
-    for (int v : g[u]) {
-        dfs_tarjan(v);
-        if (vis[v]) lowlnk[u] = min(lowlnk[u], lowlnk[v]);
-    }
-    if (lowlnk[u] == tin[u]) {
-        int v; do {
-            v = st.top(); st.pop(); vis[v] = 0;
-            rep[v] = u;
-        } while (u != v);
-    }
+  if (tin[u] != -1) { return; }
+  lowlnk[u] = tin[u] = vis[u] = cts++;
+  st.push(u);
+  for (int v : g[u]) {
+    dfs_tarjan(v);
+    if (vis[v]) lowlnk[u] = min(lowlnk[u], lowlnk[v]);
+  }
+  if (lowlnk[u] == tin[u]) {
+    int v; do {
+      v = st.top(); st.pop(); vis[v] = 0;
+      rep[v] = u;
+    } while (u != v);
+    topo.push(u);
+  }
 }
-void tarjan(int n) {
-    for (int u = 0; u < n; u++) { dfs_tarjan(u); }
+
+stack<int> tarjan(int n) {
+  for (int u = 0; u < n; u++) { dfs_tarjan(u); }
+  return topo;
 }
diff --git a/fontes/topo.h b/fontes/topo.h
index e3b991201700a343716b01f280bd29d224ddca2b..0a3530e395c2117fd3fd7dd72be8344050506708 100644
--- a/fontes/topo.h
+++ b/fontes/topo.h
@@ -1,10 +1,12 @@
 vector<bool> vis (N); stack<int> st;
+
 void dfs_topo(int u) {
     if (vis[u]) { return; }
     vis[u] = 1;
     for (int v : g[u]) { dfs_topo(v); }
     st.push(u);
 }
+
 vector<int> toposort(int n) {
   fill(visited.begin(), visited.begin() + n, false);
     vector<int> topo;