(1) 递推(记忆化搜索)求解:
利用
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[n−1]+fib[n−2](
n
≥
3
n \geq 3
n≥3)求解,复杂度为O(n)
其中
f
i
b
[
1
]
fib[1]
fib[1] = 1;
f
i
b
[
2
]
fib[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[n] =
[
f
i
b
[
n
]
f
i
b
[
n
+
1
]
]
\left[ \begin{matrix} fib[n] & fib[n + 1] \end{matrix} \right]
[fib[n]fib[n+1]]
构造一个A矩阵
F
[
n
]
F[n]
F[n] =
F
[
n
−
1
]
F[n - 1]
F[n−1] * A
可得出A =
[
0
1
1
1
]
\left[ \begin{matrix} 0 & 1 \\ 1 & 1 \end{matrix} \right]
[0111]
初始值
F
[
0
]
F[0]
F[0] =
[
0
1
]
\left[ \begin{matrix} 0 & 1 \end{matrix} \right]
[01]
这样子
F
[
n
]
F[n]
F[n] =
F
[
0
]
F[0]
F[0] *
A
n
A^n
An
便可以用快速幂求解,复杂度为O(
2
3
2^3
23
log
n
\log n
logn)
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]
fib[n] =
1
5
{1} \over {\sqrt 5}
51[(
1
+
5
2
{1 + \sqrt 5} \over {2}
21+5)
n
^n
n - (
1
−
5
2
{1 - \sqrt 5} \over {2}
21−5)
n
^n
n]
由于此公式涉及到浮点数,不适合编码。