矩阵快速幂--51nod-1242斐波那契数列的第N项

斐波那契额数列的第N项

斐波那契数列的定义如下:

F(0) = 0

F(1) = 1

F(n) = F(n - 1) + F(n - 2) (n >= 2)

(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...)

给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可。

输入

输入1个数n(1 <= n <= 10^18)。

输出

输出F(n) % 1000000009的结果。

输入样例

11

输出样例

89

思路

矩阵快速幂的模板

下面是快速幂的模板,具体怎么来的请自行百度,我们将根据这个模板写矩阵快速幂

LL Qpow(LL a, LL b)
{
    LL ret = 1, base = a;
    while(b)
    {
        if(b & 1)
            ret *= base;
        base *= base;
        b >>= 1;
    }
    return ret;
}

当我们用矩阵代替底数a时,这就涉及到ret和base的初始化和矩阵乘法

所以得出下面矩阵快速幂的模板

struct M
{
    LL m[N][N];
};
M mul(M a, M b, int n)
{
    M t;
    //初始化
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
        t.m[i][j] = 0;
    //乘法运算
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            for(int k = 1;k <= n;++k)
            t.m[i][j] = (t.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;//取模,视题目而定
    return t;
}
M M_Qpow(M a, LL b, int n)
{
    M ret, base;
    //初始化,根据快速幂中,ret = 1,ret初始化成单位矩阵
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= n;++j)
        {
            ret.m[i][j] = 0;
            ret.m[i][i] = 1;
            base.m[i][j] = a.m[i][j];
        }
    }
    //注意矩阵乘法中a*b != b*a
    while(b)
    {
        if(b & 1)
            ret = mul(ret, base, n);
        base = mul(base, base, n);
        b >>= 1;
    }
    return ret;
}

这道题中,构造这样的矩阵[fn, fn - 1] * b = [fn + 1, fn],然后求矩阵b,这个矩阵容易推算出来

b = [1, 1

1, 0]

解题代码

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <stack>

using namespace std;

typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 105;
const int MOD = 1e9 + 9;

struct M
{
    LL m[N][N];
};
M mul(M a, M b, int n)
{
    M t;
    //初始化
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
        t.m[i][j] = 0;
    //乘法运算
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            for(int k = 1;k <= n;++k)
            t.m[i][j] = (t.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
    return t;
}

M M_Qpow(M a, LL b, int n)
{
    M ret, base;
    //初始化,根据快速幂中,ret = 1,ret初始化成单位矩阵
    for(int i = 1;i <= n;++i)
    {
        for(int j = 1;j <= n;++j)
        {
            ret.m[i][j] = 0;
            ret.m[i][i] = 1;
            base.m[i][j] = a.m[i][j];
        }
    }
    //注意矩阵乘法中a*b != b*a
    while(b)
    {
        if(b & 1)
            ret = mul(ret, base, n);
        base = mul(base, base, n);
        b >>= 1;
    }
    return ret;
}

int main()
{
    M a, b;
    b.m[1][1] = 1, b.m[1][2] = 1, b.m[2][1] = 1, b.m[2][2] = 0;
    a.m[1][1] = 1, a.m[1][2] = 0;
    LL n;
    cin >> n;
    M c = mul(a, M_Qpow(b, n - 1, 2), 2);
    cout << c.m[1][1] << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/shuizhidao/p/10295449.html