问题
先看下面的问题: [ poj-3070]
Description:
In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
Given an integer n, your goal is to compute the last 4 digits of Fn.
Input
The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number −1.
Output:
For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).
Sample Input
0
9
999999999
1000000000
-1
Sample Output
0
34
626
6875
思路
之前讲过的矩阵快速幂求模求解即可。只不过本题在题目描述的过程中给出了另外一种矩阵表示。见下面证明:
由于(1)恒成立,所以当 n>=1时,等式两边同乘右边的常数矩阵,有:
本质是求解如下矩阵:
从而将斐波那契数列问题转化为矩阵乘法的问题,又可以进一步转化为矩阵快速幂。根之前的区别只是最终求解矩阵的区别。
代码
#include <iostream>
#include <cstring>
#include <fstream>
//#define LOCAL
const int maxn = 8;
const int MOD = 10000;
struct Matrix{
int mat_[maxn][maxn];
int size_;
Matrix( int s = 0 ) : size_( s )
{
std::memset( mat_, 0, sizeof(mat_) );
}
Matrix( const Matrix& rhs )
{
size_ = rhs.size_;
*this = rhs;
}
int init()
{
mat_[0][0] = 1;
mat_[0][1] = 1;
mat_[1][0] = 1;
mat_[1][1] = 0;
return 0;
}
int set_diag( int val )
{
for( int i = 0; i < size_; ++i )
{
for( int j = 0; j < size_; ++j )
mat_[i][j] = (i==j)?val:0;
}
return 0;
}
Matrix& operator=( const Matrix& rhs )
{
for( int i = 0; i < size_; ++i )
{
for( int j = 0; j < size_; ++j )
mat_[i][j] = rhs.mat_[i][j];
}
return *this;
}
Matrix operator*( const Matrix& rhs )
{
Matrix ret(2);
for( int i = 0; i < size_; ++i )
{
for( int j = 0; j < size_; ++j )
{
for( int index = 0; index < size_; ++index )
{
ret.mat_[i][j] = (ret.mat_[i][j] + (mat_[i][index]%MOD * rhs.mat_[index][j]%MOD)%MOD)%MOD;
}
}
}
return ret;
}
Matrix& operator^( int b )
{
Matrix a(*this);
Matrix ans(2);
ans.set_diag(1);
while(b)
{
if(b%2)
ans = ans * a;
a = a*a;
b /= 2;
}
*this = ans;
return *this;
}
};
int main( void )
{
#ifdef LOCAL
std::ifstream cin("input.dat");
#endif
int n = 0;
while( std::cin >> n, n != -1 )
{
if(!n)
std::cout << 0 << std::endl;
else
{
Matrix a(2);
a.init();
a^n;
std::cout << a.mat_[0][1] << std::endl;
}
}
#ifdef LOCAL
cin.close();
#endif
return 0;
}
总结
一遍过,没有遇见太大问题。感受到了引入矩阵后对于问题的简化。矩阵真是个好东西。