铁锹:呃,其实我的名字是英文缩写,不是铁锹,你们不要再给我乱起外号了
什么是矩阵?
一个 \(n\times m\) 的矩阵是由数组成的 \(n\) 行 \(m\) 列的方阵。
什么是矩阵乘法?
假设有三个矩阵 \(A, B, C\),其中 \(A\) 的列数与 \(B\) 的行数相等(假设为 \(n\))。若 \(C=A\times B\),那么 \(C_{i,j}=\sum\limits_{k=1}^n A_{i,k}\times B_{k,j}\),其中 \(C\) 的行数与 \(A\) 的行数相等,\(B\) 的列数与 \(C\) 的列数相等。
什么是矩阵快速幂?
把普通快速幂的底数换成矩阵。
铁锹:呃我要讲的就是这些,同学们可以开始做题了。
呃呃,所以模拟一下这个过程就好了?
namespace Matrix {
const int maxn = 25;
template<const int mod>
class Mat {
private:
int n, m;
public:
int a[maxn][maxn];
Mat () {}
Mat (int N, int M, bool type = 0) {
n = N, m = M;
memset(a, 0, sizeof (a));
if (type) {
for (int i = 1; i <= n; ++i)
a[i][i] = 1;
}
}
int* operator[] (int q) {
return a[q];
}
const int* operator[] (int q) const {
return a[q];
}
Mat operator* (const Mat &q) const {
Mat res(n, q.m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= q.m; ++j) {
for (int k = 1; k <= m; ++k) {
(res[i][j] += (a[i][k]
* q[k][j] % mod + mod)
% mod) %= mod;
}
}
}
return res;
}
Mat& operator*= (const Mat &q) {
return (*this) = (*this) * q;
}
Mat operator^ (const int q) const {
int y = q;
Mat res(n, n, 1), x(*this);
while (y) {
if (y & 1)
res *= x;
x *= x;
y >>= 1;
}
return res;
}
Mat& operator^= (const int &q) {
return (*this) = (*this) ^ q;
}
};
} // namespace Matrix
CF450B - Jzzhu and Sequences
游戏的第一关都会放一个稀奇古怪的东西让新手入门。
——我也不知道是哪位 TFer 说的
我看了大半天没看懂样例最后发现不是斐波那契???
那也和斐波那契一样啊。
我们都知道,斐波那契的加速矩阵是这样的:
\[[f_{i - 1},f_i]=[f_i,f_{i + 1}]\times\begin{bmatrix}0&1\\1&1 \end{bmatrix} \]那我们把 \(f_{i-1}\to f_{i+1}\) 的系数改成减就好了。
namespace XSC062 {
using namespace fastIO;
using namespace Matrix;
const int mod = 1e9 + 7;
int x, y, m;
Mat<mod> A, B;
int main() {
read(x);
read(y);
read(m);
if (m == 1) {
printf("%lld", (x % mod + mod) % mod);
return 0;
}
if (m == 2) {
printf("%lld", (y % mod + mod) % mod);
return 0;
}
A = Mat<mod>(1, 2);
B = Mat<mod>(2, 2);
A[1][1] = x;
A[1][2] = y;
B[1][2] = -1;
B[2][1] = B[2][2] = 1;
A *= (B ^= (m - 2));
printf("%lld", A[1][2]);
return 0;
}
} // namespace XSC062