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

  • 相关阅读:
    有价值的终会被人发现和承认
    Sql中存在斜杠“/”怎么办?
    JSONObject和JSONArray(json-lib-2.4)的基本用法
    如何设定linux系统时间
    动态创建的文本框想要加上jQuery的datepicker功能变成日期选择控件该怎么办?
    如果$.ajax函数迟迟得不到响应,那么最有可能出错的地方是请求参数写错了
    Notepad2替代系统自带的记事本Notepad
    css属性与js中style对象的属性对应表
    day02_js学习笔记_01_js的简介、js的基本语法
    Eclipse/MyEclipse的快捷键以及文档注释、多行注释的快捷键
  • 原文地址:https://www.cnblogs.com/chelinger/p/11586744.html
Copyright © 2020-2023  润新知