题目描述
Winder 最近在学习 fibonacci 数列的相关知识。我们都知道 fibonacci 数列的递推公式是F(n) = F(n - 1) + F(n - 2)(n >= 2 且 n 为整数)。
Winder 想知道的是当我们将这个递推式改为F(n) = a * F(n - 1) + b * F(n - 2)(n >= 2 且 n 为整数)时我们得到的是怎样的数列。但是,Winder 很懒,所以只能由你来帮他来完成这件事。
注意,这里我们依然令 F(0)=F(1)=1。
输入格式
输入第一行三个正整数 q, a, b。
接下来有 q 行,每行一个自然数 n。
对于50%的数据,1 <= q、n <= 1000。
对于80%的数据,1 <= q、n <= 100000。
对于100%的数据,1 <= q <= 100000,1 <= n <= 1000000000,1 <= a、b <= 1000。
输出格式
输出一行一个整数 F(n),由于结果可能会很大,Winder 要求输出结果对 2013 取模,即将 F(n)对2013求余后输出。
样例输入
5 4 5
2
4
8
16
32
样例输出
9
209
1377
182
9
方法一:
刚开始拿到题目的时候第一反应是按要求做一个递归算法,但是后来发现递归的代价太大,可能会过不了。
方法二:
和方法一一个思路,但是使用了非递归算法,虽然肯定不是最优算法,但是应该可以得一个基础分了。
#include <iostream> using namespace std; int fibonacci(int n, int a, int b) { if (n <= 1) return 1; else { int current = 0; int pre1 = 1; int pre2 = 1; for (int i = 2; i <= n; i++) { current = (a * pre1 + b * pre2) % 2013; pre2 = pre1; pre1 = current; } return current; } } int main() { int q, a, b; cin >> q >> a >> b; int *result = new int[q]; for (int i = 0; i < q; i++) { int n; cin >> n; result[i] = fibonacci(n, a, b); } for (int i = 0; i < q; i++) { cout << result[i] << endl; } delete[]result; return 0; }
方法三:
这个是在理解了矩阵快速幂的思想基础上,进行改进的一个算法,把问题规模直接降了一大截。
#include <cstdio> #include <cstring> #include <cmath> #include <iostream> using namespace std; const int MOD = 2013; struct matrix { //矩阵 int m[2][2]; }ans; matrix multi(matrix a, matrix b) { //矩阵相乘,返回一个矩阵 matrix tmp; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { tmp.m[i][j] = 0; for (int k = 0; k < 2; k++) tmp.m[i][j] = (tmp.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD; } } return tmp; } matrix matrix_pow(matrix a, int n) { //矩阵快速幂,矩阵a的n次幂 ans.m[0][0] = ans.m[1][1] = 1; //初始化为单位矩阵 ans.m[0][1] = ans.m[1][0] = 0; while (n) { if (n & 1) ans = multi(ans, a); a = multi(a, a); n >>= 1; } return ans; } int main() { int q, n, a, b; cin >> q >> a >> b; int* result = new int[q]; matrix mul; mul.m[0][0] = a; mul.m[0][1] = b; mul.m[1][0] = 1; mul.m[1][1] = 0; for (int i = 0; i < q; i++) { int n; cin >> n; matrix mm = matrix_pow(mul, n - 1); result[i] = (mm.m[0][0] + mm.m[0][1])%MOD; } for (int i = 0; i < q; i++) { cout << result[i] << endl; } delete[]result; return 0; }
第一次做的时候因为最后一步的时候在result[i] = (mm.m[0][0] + mm.m[0][1])%MOD的时候忘记
了加这个“%MOD”,导致结果一直有部分不对,调试了将近一个上午(好惨)。