洛谷 P1962 斐波那契数列

题意简述

$ a[1]=a[2]=1 \( \) a[x]=a[x-2]+a[x-1] (x>2) $
求a数列的第n项对1000000007取余的值。

题解思路

矩阵加速
设$$ F=\begin{bmatrix} 0&1\1&1\end{bmatrix}, G=\begin{bmatrix} 1\1\end{bmatrix}$$
则$$ \begin{bmatrix} a[n-1]\a[n]\end{bmatrix} = G * F ^ {n - 2} (n > 2)$$

代码

#include <cstdio>
typedef long long ll;
const int mod = 1000000007;
int T, N;
ll n;
struct Matrix
{
	int a[4][4];
	Matrix& operator =(const Matrix& x)
	{
		for (register int i = 1; i <= N; ++i)
			for (register int j = 1; j <= N; ++j)
				a[i][j] = x.a[i][j];
		return *this;
	}
};
Matrix a, b, c;
Matrix Mul(const Matrix& x, const Matrix& y)
{
	Matrix s;
	for (register int i = 1; i <= N; ++i)
		for (register int j = 1; j <= N; ++j)
			s.a[i][j] = 0;
	for (register int i = 1; i <= N; ++i)
		for (register int j = 1; j <= N; ++j)
			for (register int k = 1; k <= N; ++k)
				s.a[i][j] = (s.a[i][j] + (ll)x.a[i][k] * y.a[k][j] % mod) % mod;
	return s;
}
Matrix _pow(Matrix x, ll y)
{
	Matrix s;
	for (register int i = 1; i <= N; ++i)
		for (register int j = 1; j <= N; ++j)
			s.a[i][j] = (i == j);
	for (; y; y >>= 1, x = Mul(x, x)) if (y & 1) s = Mul(s, x);
	return s;
}
int main()
{
	N = 3;
	scanf("%lld", &n);
	c.a[1][1] = c.a[1][2] = 1;
	a.a[1][1] = a.a[1][2] = a.a[2][1] = 1;
	if (n <= 2) {printf("1\n"); return 0; }
	b = Mul(c, _pow(a, n - 2));
	printf("%d\n", b.a[1][1]);
}
posted @ 2018-10-17 19:53  xuyixuan  阅读(182)  评论(0编辑  收藏  举报