斐波那契(矩阵快速幂)

今天随便看了看矩阵的相关内容,顺势学习了一下矩阵构造和矩阵快速幂,然后又顺道写了这个入门题。

斐波那契数列,即 F i b ( n ) = F i b ( n − 1 ) + F i b ( n − 2 ) Fib(n)=Fib(n-1)+Fib(n-2) Fib(n)=Fib(n1)+Fib(n2),就这么一个数列,显然可以直接递推求解,时间复杂度 O ( N ) O(N) O(N),似乎没什么问题。

然后就遇到了这个, n n n的取值范围最大是 2 × 1 0 9 2\times10^9 2×109的这么一个题,线性显然不能满足时间限制,然后就需要用矩阵快速幂求解了。

F ( n ) F(n) F(n)表示一个 1 × 2 1\times2 1×2的矩阵 [ F i b ( n ) , F i b ( n + 1 ) ] [Fib(n),Fib(n+1)] [Fib(n)Fib(n+1)],推道依然按照递推式,我们发现, F ( n + 1 ) F(n+1) F(n+1)显然就是 F ( n ) F(n) F(n)中将第二项前移做为第一项,第一项和原第二项的和作为新的第二项(递推),即相当于每次乘以了一个 2 × 2 2\times2 2×2的矩阵,我们可以求出这个矩阵是 [ 0 1 1 1 ] \left[ \begin{matrix} 0&1\\1&1 \end{matrix} \right] [0111]
我们记这个矩阵为 Z Z Z

也就是说, F ( 1 ) = F ( 0 ) × Z F(1)=F(0)\times Z F(1)=F(0)×Z,相应的, F ( 2 ) = F ( 1 ) × Z = F ( 0 ) × Z × Z = F ( 0 ) × Z 2 F(2)=F(1)\times Z=F(0)\times Z\times Z=F(0)\times Z^2 F(2)=F(1)×Z=F(0)×Z×Z=F(0)×Z2,依次类推,而我们需要求的 F i b ( n ) Fib(n) Fib(n)实际上就是 F ( n ) F(n) F(n)第一项,也就是说,只要求得了 F ( n ) F(n) F(n),就相当于求得了 F i b ( n ) Fib(n) Fib(n),于是问题就转换为了矩阵快速幂。

#include <bits/stdc++.h>
using namespace std;
int n;
const int mod = 10000;
struct p{
    
    
	int arr[3][3];
	p(){
    
    
		
	}
	p(int a[3][3]){
    
    
		for (int i = 1; i <= 2; i++){
    
    
			for (int j = 1; j <= 2; j++){
    
    
				arr[i][j] = a[i][j];
			}
		}
	}
	p operator * (const p& a){
    
    
		p temp;
		temp.arr[1][1] = this->arr[1][1] * a.arr[1][1] + this->arr[1][2] * a.arr[2][1];
		temp.arr[1][2] = this->arr[1][1] * a.arr[1][2] + this->arr[1][2] * a.arr[2][2];
		temp.arr[2][1] = this->arr[2][1] * a.arr[1][1] + this->arr[2][2] * a.arr[2][1];
		temp.arr[2][2] = this->arr[2][1] * a.arr[1][2] + this->arr[2][2] * a.arr[2][2];
		return temp;
	}
	void MOD(){
    
    
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				this->arr[i][j] %= mod;
	}
};
int te[3][3];
int one[3][3];
p qpow(p temp, int n){
    
    
	p ans = p(one);
	ans.MOD();
	while (n){
    
    
		if (n & 1){
    
    
			ans = ans * temp;
			ans.MOD();
		}
		n >>= 1;
		temp = temp * temp;
		temp.MOD();
	}
	ans.MOD();
	return ans;
}
int main() {
    
    
	ios::sync_with_stdio(0);
	te[1][1] = 0, te[1][2] = te[2][1] = te[2][2] = 1;
	one[1][1] = one[2][2] = 1;
	one[1][2] = one[2][1] = 0;
	while (cin >> n && (~n)){
    
    
		p ans = qpow(p(te), n);
		cout << ans.arr[2][1] << "\n";
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/105419248
今日推荐