-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathmatrix_minified.cpp
134 lines (114 loc) · 2.95 KB
/
matrix_minified.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <bits/stdc++.h>
using namespace std;
const int M = 5, MOD = 1e9 + 7;
/**
* Minified matrix class for competitive programming.
* The time complexity of the matrix power is O((M^3).log(n)),
* where "M" is the size of the matrix, and "n" is the exponent.
*/
class matrix {
int rows, cols;
int mat[M][M] = {};
public:
/**
* Constructs an identity matrix of a certain size.
*
* @param n the size of the identity matrix.
*
* @return the constructed identity matrix of size (n x n).
*/
static matrix eye(int n) {
matrix res(n, n);
for (int i = 0; i < n; ++i) {
res.mat[i][i] = 1;
}
return res;
}
/**
* Constructs a new matrix.
*
* @param n the number of rows in the matrix.
* @param m the number of columns in the matrix.
* @param data the data to fill the matrix with.
*/
matrix(int n = 1, int m = 1, const vector<int>& data = {}) {
rows = n;
cols = m;
set(data);
}
/**
* Fills the matrix with the given data.
*
* @param data the data to fill the matrix with.
*/
void set(const vector<int>& data) {
int k = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
if (k >= data.size()) {
return;
}
mat[i][j] = data[k++];
}
}
}
/**
* @return a reference of the cell (i, j) in this matrix.
*/
int& operator()(int i, int j) {
return mat[i][j];
}
/**
* Multiplies this matrix by the given one.
*
* @param rhs the matrix on the right hand side.
*
* @return the resultant matrix after multiplication.
*/
matrix operator*(const matrix& rhs) const {
matrix res(rows, rhs.cols);
for (int i = 0; i < res.rows; ++i)
for (int j = 0; j < res.cols; ++j)
for (int k = 0; k < rhs.rows; ++k)
res.mat[i][j] = (res.mat[i][j] + mat[i][k] * 1LL * rhs.mat[k][j]) % MOD;
return res;
}
/**
* Raises this matrix to the power of a certain number.
*
* @param exp the exponent to raise the matrix with.
*
* @return the resultant matrix after exponentiation.
*/
matrix operator^(long long exp) const {
matrix base = *this;
matrix res = eye(rows);
while (exp > 0) {
if (exp & 1) res = (res * base);
exp >>= 1;
base = (base * base);
}
return res;
}
};
/**
* Sample driver program.
*
* This is an example of calculating Fibonacci(n) mod (10^9 + 7) for very
* large values of "n" (i.e. 1 <= n <= 10^18).
*/
int main() {
long long n;
cin >> n;
matrix A(2, 2, {
0, 1,
1, 1
});
matrix b(2, 1, {
0,
1
});
matrix r = (A ^ (n - 1)) * b;
cout << r(1, 0) << endl;
return 0;
}