Skip to content
Snippets Groups Projects
Commit 34135a80 authored by Bruno Freitas Tissei's avatar Bruno Freitas Tissei
Browse files

Add fast matrix pow

parent 50389063
No related branches found
No related tags found
No related merge requests found
#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;
}
#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;
}
/**
* 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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment