<Sicily>Fibonacci 2

一、题目描述

In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn-1 + Fn-2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

Given an integer n, your goal is to compute the last Fn mod (10^9 + 7).

二、输入

The input test file will contain a single line containing n (n ≤ 2^31-1).

There are multiple test cases!

三、输出

For each test case, print the Fn mod (10^9 + 7).

例如:
输入:9
输出:34

四、解题思路

这次要求输入的数会很大,使用递归或者动态规划的方法时,会超时。

所以只能使用矩阵方法求解。把问题转换为矩阵相乘,矩阵相乘可以通过快速幂的求解方法提高效率。

1、矩阵表示
这里写图片描述

2、矩阵推导公式
这里写图片描述

3、带入f(0),f(1)
这里写图片描述

这里写图片描述

由上面的公式能可知,可以把原问题转换成求一个矩阵的n次幂问题。

4、整数n次方的快速幂求法
例如求3的999次方
这里写图片描述

这里写图片描述

快速幂求法

这里写图片描述

5、使用同样的方法求一矩阵n次方

五、代码

#include <iostream>
using namespace std;

const long long int MODE = 1000000000+7;    //当数太大是取模(题目要求)

struct Matrix     //矩阵
{
    long long int mat[2][2];
};

Matrix matrixMultiply(Matrix m1, Matrix m2) //两个矩阵乘积
{
    Matrix result;

    for(int i = 0; i < 2; i++)  //第i行(m1)
    {
        for(int j = 0; j < 2; j++)  //第j列(m2)
        {
            result.mat[i][j] = 0;
            for(int k = 0; k < 2; k++)  //m1的第i行乘以m2的第j列
            {
                result.mat[i][j] += m1.mat[i][k] * m2.mat[k][j];
                result.mat[i][j] %= MODE;
            }
        }
    }

    return result;
}

Matrix exponentiate(Matrix m1, long long int n) //矩阵的n次幂
{
    Matrix result = {1, 0, 1, 0};
    while(n)
    {
        if(n & 1) result = matrixMultiply(result, m1);  //当n为奇数时
        m1 = matrixMultiply(m1, m1);
        n >>= 1;
    }

    return result;
}


int main()
{
    Matrix baseMatrix = {1, 1, 1, 0};
    Matrix resultMatrix;
    long long int n, fn;
    while(cin >> n)
    {
        if(n == 0 || n == 1)
        {
            cout << n << endl;
            continue;
        }

        resultMatrix = exponentiate(baseMatrix, n);
        fn = resultMatrix.mat[0][1];
        cout << fn << endl;
    }

    return 0;

}
posted @ 2016-06-08 00:14  chenximcm  阅读(138)  评论(0编辑  收藏  举报