diff --git a/contests/Cadernaveis/DESCULPA.cpp b/contests/Cadernaveis/DESCULPA.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b05311d520d3c904c7fa1f0b8c97290fd76d454
--- /dev/null
+++ b/contests/Cadernaveis/DESCULPA.cpp
@@ -0,0 +1,46 @@
+#include <bits/stdc++.h>
+ 
+#define MAX 1010
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+ 
+#define fi first
+#define se second
+#define sz size()
+#define pb push_back
+#define ende '\n'
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+ 
+using namespace std;
+ 
+typedef long long ll;
+typedef pair<int,int> ii;
+ 
+int dp[60][MAX];
+int v[MAX], w[MAX];
+ 
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+ 
+  int c, f, cas = 1;
+  while (cin >> c >> f && (c || f)) {
+    memset(dp, 0, sizeof dp);
+    for (int i = 1; i <= f; ++i)
+      cin >> w[i] >> v[i];
+ 
+    for (int i = 1; i <= f; ++i)
+      for (int j = 0; j <= c; ++j)
+        if (j >= w[i])
+          dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i]] + v[i]);
+        else
+          dp[i][j] = dp[i-1][j];
+    
+    cout << "Teste " << cas << ende;
+    cout << dp[f][c] << ende << ende;
+		cas++;
+  }
+ 
+  return 0;
+}
diff --git a/contests/Cadernaveis/TOPOLAND.cpp b/contests/Cadernaveis/TOPOLAND.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3db4470475f6fb31690d17305336dec59de260cd
--- /dev/null
+++ b/contests/Cadernaveis/TOPOLAND.cpp
@@ -0,0 +1,102 @@
+#include <bits/stdc++.h>
+
+#define MAX 101010
+#define MOD 1000000007
+#define inf 0x3f3f3f3f
+
+#define fi first
+#define se second
+#define sz size()
+#define pb push_back
+#define all(x) (x).begin(), (x).end()
+#define rall(x) (x).rbegin(), (x).rend()
+
+using namespace std;
+
+typedef long long ll;
+typedef pair<int,int> ii;
+
+ll N, tree[4 * MAX], v[MAX];
+
+void build_tree(int node = 1, int a = 0, int b = N) {
+  if (a > b)
+    return;
+
+  if (a == b) {
+    tree[node] = v[a];
+    return;
+  }
+
+  build_tree(node * 2, a, (a + b) / 2);
+  build_tree(node * 2 + 1, 1 + (a + b) / 2, b);
+
+  tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
+}
+
+
+void update_tree(int idx, ll val, int node = 1, int a = 0, int b = N) {
+  if (a > b || a > idx || b < idx)
+    return;
+
+  if (a == b) {
+    tree[node] = val;
+    return;
+  }
+
+  update_tree(idx, val, node * 2, a, (a + b) / 2);
+  update_tree(idx, val, node * 2 + 1, 1 + (a + b) / 2, b);
+
+  tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
+}
+
+
+int query_tree(int i, int j, int node = 1, int a = 0, int b = N) {
+  if (a > b || a > j || b < i)
+    return 0;
+
+  if (a >= i && b <= j)
+    return tree[node];
+
+  int res1 = query_tree(i, j, node * 2, a, (a + b) / 2);
+  int res2 = query_tree(i, j, node * 2 + 1, 1 + (a + b) / 2, b);
+
+  return max(res1, res2);
+}
+
+
+int main() {
+  ios::sync_with_stdio(0);
+  cin.tie(0);
+
+  ll t, n, m;
+  cin >> t;
+  for (int cas = 0; cas < t; ++cas) {
+    cout << "Testcase " << cas << ":\n";
+    cin >> n >> m;
+    N = n;
+
+    for (int i = 0; i < n; ++i)
+      cin >> v[i];
+    build_tree();
+
+    ll q, a, b;
+    string op;
+    cin >> q;
+    for (int i = 0; i < q; ++i) {
+      cin >> op;
+      if (op[0] == 'A') {
+        cin >> a;
+        m += a;
+      } else if (op[0] == 'B') {
+        cin >> a >> b;
+        update_tree(a, b);
+      } else {
+        cin >> a >> b;
+        cout << abs(m - query_tree(a, b)) << '\n';
+      }
+    }
+    cout << '\n';
+  }
+
+  return 0;
+}
diff --git a/math/fast_matrix_pow.cpp b/math/fast_matrix_pow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c8c02ef313cf747c3d507057ee5b762788c46222
--- /dev/null
+++ b/math/fast_matrix_pow.cpp
@@ -0,0 +1,63 @@
+/**
+ * Fast Matrix Exponentiation
+ *
+ * Complexity (Time): O(K^3 log n)
+ * Complexity (Space): O(K^2)
+ */
+
+// This algorithm is used to solve recurrences such as:
+//   f(n) = x1 * f(n - 1) + x2 * f(n - 1) + ... + xk * f(n - k)
+//
+// It works by defining this recurrence as a linear combination,
+// for example (k = 2):
+//   f(n) = [x1  x2] [f(n - 1)]
+//                   [f(n - 2)]
+// It can be rewriten as:
+//   [  f(n)  ] = [x1  x2] [f(n - 1)]
+//   [f(n - 1)]   [ 1   0] [f(n - 2)]
+//
+// And that is solved by calculating the following matrix power:
+//   [x1  x2]^n
+//   [ 1   0]
+
+#define K 2
+
+struct mat {
+  ll m[K][K];
+
+  // Matrix multiplication - O(k^3)
+  mat operator*(mat a) {
+    mat aux;
+
+    for(int i = 0; i < K; i++)
+      for(int j = 0; j < K; j++) {
+        ll sum = 0;
+        for(int k = 0; k < K; k++)
+          sum += (m[i][k] * a.m[k][j]) % MOD;
+        aux.m[i][j] = sum % MOD;
+      }
+
+    return aux;
+  }
+};
+
+
+// Fast exponentiation (can be used with integers as well) - O(log n)
+ll mat_pow(mat in, ll n) {
+  mat ans, b = in;
+
+  // Set ans as identity matrix
+  memset(ans.m, 0, sizeof ans.m);
+  for (int i = 0; i < K; ++i)
+    ans.m[i][i] = 1;
+
+  while (n) {
+    if (n & 1)
+      ans = ans * b;
+
+    n >>= 1;
+    b = b * b;
+  }
+
+  return ans;
+}