斐波那契
迭代的斐波那契
斐波那契有很多种写法,不会递归的同学就会这样写:
int fib0(int n) { int a = 1; int b = 1; int c; if(n == 1 || n == 2) { return 1; } for (int i = 2; i < n; i++) { c = a + b; b = a; a = c; } return c; }
#define MAXN 1000 int fib_dp(int n) { int f[MAXN]; f[1] = 1; f[2] = 1; if (n == 1 || n == 2) { return 1; } for (int i = 2; i <= n; i++) { f[i] = f[i-1] + f[i-2]; } return f[n]; }
递归写法的斐波那契
递归的写法:
int fib1(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { return fib1(n-1) + fib1(n-2); } }
带记忆的递归写法:
#define MAXN 1000 int a[MAXN]; void fib2_init(void) { memset(a, -1, sizeof(a)); a[0] = 1; a[1] = 1; } int fib2(int n) { if (a[n] > 0) { return a[n]; } else { a[n] = fib2(n-1) + fib2(n-2); return a[n]; } } // 调用的时候就必要先初始化下 int main() { fib2_init(); fib2(n); }
采用矩阵快速求斐波那契
然而,上面的各种写法都不是最快的写法。由矩阵的知识可以推出:
[An ] [ An ] [0 1] . . [An-1] = = . [An+1] [ An-1 + An] [1 1] . . [An ]
[0 1] N . . [0] [An ] 令 A = , 则 A . ==> [1 1] . . [1] [An+1]
当然要写出上面的程序还需要会 求矩阵乘法,求阶乘。
矩阵乘法:
struct matrix { int m[2][2]; }; matrix matrix_multi(matrix a, matrix b) { matrix c; memset(&c, 0, sizeof(matrix)); // 将数据初始化为0 for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { c.m[i][j] = c.m[i][j] + a.m[i][k] * b.m[k][j]; } } } return c; }
求阶乘
在int整数类型的时候,我们可以这样求阶乘:
int pow(int a, int n) { if (n == 1) { return a; } else if (n % 2 == 0) { int b = pow(a, n / 2); return b * b; } else if (n % 2 == 1) { return a * pow(a, n-1); } }
现在换成是矩阵:
matrix matrix_pow(matrix a, int n) { if (n == 1) { return a; } else if (n % 2 == 0) { matrix b = matrix_pow(a, n / 2); return matrix_multi(b, b); } else if (n % 2 == 1) { return matrix_multi(a, matrix_pow(a, n-1)); } }
最后我们还需要一个包装函数:
int fib_matrix(int n) { if (n == 0) { return 0; } matrix init; init.m[0][0] = 0; init.m[0][1] = 1; init.m[1][0] = 1; init.m[1][1] = 1; matrix t = matrix_pow(init, n); int res = t.m[0][1]; return res; }