您的位置:首页 > 其它

51nod 巨大的斐波那契数列(矩阵快速幂),递推式优化的好模板!!!!!!!

2015-10-24 16:12 453 查看
斐波那契数列的定义如下:

F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2) (n >= 2)

(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...)
给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可。

Input
输入1个数n(1 <= n <= 10^18)。


Output
输出F(n) % 1000000009的结果。


Input示例
11


Output示例
89


著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。

作者:王希

链接:http://www.zhihu.com/question/23582123/answer/40464211

来源:知乎

矩阵递推关系

学过代数的人可以看出,下面这个式子是成立的:

&lt;img src="https://pic1.zhimg.com/d900e0509f9d056286ff9455e7706f90_b.jpg" data-rawwidth="284" data-rawheight="69" class="content_image" width="284"&gt;不停地利用这个式子迭代右边的列向量,会得到下面的式子:

不停地利用这个式子迭代右边的列向量,会得到下面的式子:

&lt;img src="https://pic3.zhimg.com/c564ec78cf8008541bc1bbcfd4a70dea_b.jpg" data-rawwidth="270" data-rawheight="70" class="content_image" width="270"&gt;这样,问题就转化为如何计算这个矩阵的n次方了,可以采用快速幂的方法。

这样,问题就转化为如何计算这个矩阵的n次方了,可以采用快速幂的方法。快速幂_百度百科是利用结合律快速计算幂次的方法。比如我要计算,我们知道,而可以通过来计算,而可以通过计算,以此类推。通过这种方法,可以在O(lbn)的时间里计算出一个数的n次幂。快速幂的代码如下:

#include <iostream>
#include <algorithm>
#include <cmath>
#define MOD 1000000009
#define N 2
using namespace std;

struct Matrix
{
long long v

;
};

Matrix matrix_mul(Matrix A, Matrix B, long long m)
{
Matrix ans;

for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
ans.v[i][j] = 0;
for (int k = 0; k < N; k ++)
{
ans.v[i][j] += (A.v[i][k] * B.v[k][j]) % m;
}
ans.v[i][j] %= m;
}
}
return ans;
}

Matrix matrix_pow(Matrix C, long long n, long long m)
{
Matrix ans = {1, 0, 0, 1};
while (n)
{
if (n & 1)
ans = matrix_mul(ans, C, m);
C = matrix_mul(C, C, m);
n >>= 1;
}
return ans;
}

int main()
{
long long n;
Matrix temp1 = {1, 1, 1, 0}, temp2 = {1, 0, 1, 0}; // temp2{f[2],0,f[1],0}!!!!!
while (cin >> n)
{
if (n < 2)
{
cout << 1 << endl;
continue;
}
Matrix res = matrix_pow(temp1, n - 2, MOD);
res = matrix_mul(res, temp2, MOD);
cout << res.v[0][0] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: