poj3070 Fibonacci(矩阵快速幂取模)
题目链接: poj2070 Fibonacci
\(Fibonacci\) 数列有: \(F_0=0, F_1=1, F_n=F_{n-1}+F_{n-2}(n\ge 2)\) .
于是
\[\begin{align}
\begin{pmatrix} F_{n+1} & F_n \\ F_n & F_{n-1}\end{pmatrix}
&=\begin{pmatrix} 1 & 1 \\ 1 & 0\end{pmatrix}
\begin{pmatrix} F_{n} & F_{n-1} \\ F_{n-1} & F_{n-2}\end{pmatrix} \\
&=\cdots \\
&=\begin{pmatrix} 1 & 1 \\ 1 & 0\end{pmatrix}^{n-1}
\begin{pmatrix} F_2 & F_1 \\ F_1 & F_0\end{pmatrix} \\
&=\begin{pmatrix} 1 & 1 \\ 1 & 0\end{pmatrix}^n
\end{align}
\]
事实上题目已经给出了公式,直接套用就好了。
定义一个矩阵结构体并重载 \(*\) ,矩阵快速幂的写法就与普通快速幂几乎一样了。
/**
* poj3070 Fibonacci
* 矩阵快速幂取模
*/
#include <iostream>
#include <climits>
#include <vector>
using namespace std;
typedef long long LL;
struct Matrix
{
LL mod;
vector<vector<LL> > m;
Matrix(int row, int col, LL mod = LLONG_MAX)
{
this->mod = mod;
m.resize(row, vector<LL>(col));
}
Matrix operator * (const Matrix &t) const
{
int row = m.size(), col = t.m[0].size(), cnt = m[0].size();
Matrix res(row, col, mod);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
for (int k = 0; k < cnt; ++k) {
res.m[i][j] += m[i][k]*t.m[k][j]%mod;
res.m[i][j] %= mod;
}
}
}
return res;
}
};
Matrix fastPow(Matrix a, LL b, LL mod = LLONG_MAX)
{
int n = a.m.size();
Matrix t(n, n, mod);
for (int i = 0; i < n; ++i) t.m[i][i] = 1;
while (b) {
if (b&1) t = t*a;
a = a*a;
b >>= 1;
}
return t;
}
const int mod = 10000;
int main()
{
int n;
Matrix A(2, 2, mod);
A.m[0][0] = A.m[0][1] = A.m[1][0] = 1;
while (cin >> n && ~n) {
cout << fastPow(A, n, mod).m[0][1] << endl;
}
return 0;
}
模板总结
在此总结一个存储矩阵的模板,以后遇到题目再完善
struct Matrix
{
LL mod;
vector<vector<LL> > m;
Matrix(int row, int col, LL mod = LLONG_MAX)
{
this->mod = mod;
m.resize(row, vector<LL>(col));
}
Matrix operator * (const Matrix &t) const
{
int row = m.size(), col = t.m[0].size(), cnt = m[0].size();
Matrix res(row, col, mod);
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
for (int k = 0; k < cnt; ++k) {
res.m[i][j] += m[i][k]*t.m[k][j]%mod;
res.m[i][j] %= mod;
}
}
}
return res;
}
};