题目描述:
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”,导致结果一直有部分不对,调试了将近一个上午。

网友评论