51Nod 1242 斐波那契数列的第N项(推导+矩阵快速幂)

基准时间限制: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;
}

参考:http://blog.zhengyi.one/fibonacci-in-logn.html

猜你喜欢

转载自blog.csdn.net/CJ_035/article/details/81741365