关于Fibonacci数列的几种求法与POJ 3070

(1) 递推(记忆化搜索)求解:

利用 f i b [ n ] = f i b [ n 1 ] + f i b [ n 2 ] fib[n] = fib[n - 1] + fib[n - 2] ( n 3 n \geq 3 )求解,复杂度为O(n)
其中 f i b [ 1 ] fib[1] = 1;
f i b [ 2 ] fib[2] = 1;

参考代码如下:
#include <iostream>
#include <cstdio>
using namespace std; 
long long fib[100000];
const int mod = 1e9 + 7;
int main(){
	int n, i;
	scanf("%d", &n);
	fib[1] = 1;
	fib[2] = 1;
	for(i = 3; i <= n; i++)
		fib[i] = (fib[i - 1] + fib[i - 2]) % mod;
	printf("%lld\n", fib[n]);
	return 0;
}

(2) 利用矩阵乘法:

(这就是poj3070的解法,它的题意为:求Fibonacci第n项的后4位(%10000))
我们设 F [ n ] F[n] =
[ f i b [ n ] f i b [ n + 1 ] ] \left[ \begin{matrix} fib[n] &amp; fib[n + 1] \end{matrix} \right]
构造一个A矩阵
F [ n ] F[n] = F [ n 1 ] F[n - 1] * A
可得出A =
[ 0 1 1 1 ] \left[ \begin{matrix} 0 &amp; 1 \\ 1 &amp; 1 \end{matrix} \right]
初始值 F [ 0 ] F[0] =
[ 0 1 ] \left[ \begin{matrix} 0 &amp; 1 \end{matrix} \right]
这样子 F [ n ] F[n] = F [ 0 ] F[0] * A n A^n
便可以用快速幂求解,复杂度为O( 2 3 2^3 log n \log n )

POJ3070代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int mod = 10000;
void mul(int f[2], int a[2][2]){
	int c[2], j, k;
	memset(c, 0, sizeof(c));
	for(j = 0; j < 2; j++)
		for(k = 0; k < 2; k++){
			c[j] = (c[j] + (long long)f[k] * a[k][j]) % mod;
		}
	memcpy(f, c, sizeof(c)); 
}
void mulmyself(int a[2][2]){
	int c[2][2];
	int i, j, k;
	memset(c, 0, sizeof(c));
	for(i = 0; i < 2; i++)
		for(j = 0; j < 2; j++)
			for(k = 0; k < 2; k++)
				c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j]) % mod;
	memcpy(a, c, sizeof(c));
}
int main(){
	int n,i;
	while(1){
		scanf("%d", &n);
		if(n == -1) break;
		int f[2] = {0, 1};
		int a[2][2] = {{0, 1}, {1, 1}};
		while(n > 0){//快速幂
			if(n & 1) mul(f, a);
			mulmyself(a);
			n >>= 1;
		}
		printf("%d\n", f[0]);
	}
	return 0;
} 

(3) 通项公式:

f i b [ n ] fib[n] = 1 5 {1} \over {\sqrt 5} [( 1 + 5 2 {1 + \sqrt 5} \over {2} ) n ^n - ( 1 5 2 {1 - \sqrt 5} \over {2} ) n ^n ]
由于此公式涉及到浮点数,不适合编码。

猜你喜欢

转载自blog.csdn.net/linwenqidbk/article/details/100059622