算法设计与分析 1.2 不一样的fibonacci数列 (矩阵快速幂思想)

题目描述

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”,导致结果一直有部分不对,调试了将近一个上午(好惨)。

原文地址:https://www.cnblogs.com/chelinger/p/11586744.html