• 矩阵快速幂--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;
    }
    
  • 相关阅读:
    exec
    eval
    Python--day23--类的命名空间
    Python--day23--初识面向对象复习
    Python--day22--面向对象的交互
    Python--day21--异常处理
    Python--day21--包
    Python--day21--复习
    Python--day20--模块的导入
    动态加载布局的技巧
  • 原文地址:https://www.cnblogs.com/shuizhidao/p/10295449.html
Copyright © 2020-2023  润新知