基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
斐波那契数列的定义如下:
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
一开始看到用矩阵快速幂的做法,也是懵了一下(怪我太渣了),看到解释后,自己推了一遍公式就理解了。。。
矩阵算法
为了正确高效的计算斐波那契数列,我们首先需要了解以下这个矩阵等式:
为了推导出这个等式,我们首先有:
随即得到:
同理可得:
所以,看到这里应该理解了吧!不过我们还要再推导两个未知量:
最后,要求出Fn,只需求出上述的矩阵的n次方,ans[][]矩阵作为最后的结果,即Fn = ans[0][1];
#include<iostream>
#include<algorithm>
#define mod 1000000009
using namespace std;
typedef long long ll;
struct node
{
ll c[2][2];
}ans;
node matMul(node a, node b)//矩阵乘法
{
node tmp;
tmp.c[0][0] = 0; tmp.c[0][1] = 0;
tmp.c[1][0] = 0; tmp.c[1][1] = 0;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 2; k++)
{
tmp.c[i][j] += a.c[i][k] * b.c[k][j];
tmp.c[i][j] %= mod;
}
}
}
return tmp;
}
void pow(ll n)//矩阵快速幂
{
node tmp;
tmp.c[0][0] = 1; tmp.c[0][1] = 1;
tmp.c[1][0] = 1; tmp.c[1][1] = 0;
while (n)
{
if (n & 1)
ans = matMul(ans, tmp);
tmp = matMul(tmp, tmp);
n >>= 1;
}
}
int main()
{
ll n;
cin >> n;
ans.c[0][0] = 1;ans.c[0][1] = 0;
ans.c[1][0] = 0;ans.c[1][1] = 1;//初始化为单位矩阵
pow(n);
printf("%lld\n", ans.c[0][1]);
return 0;
}