关于矩阵快速幂的一点点理解

本文有一些地方引用了博客:矩阵快速幂基础讲解 - 林夕-梦 - 博客园 (cnblogs.com)

如果有侵权请联系删除

矩阵快速幂算法篇

看了一个整数数的快速幂,现在我们就正式介绍矩阵快速幂算法。假如现在有一个n*n的方阵A。所谓方阵就是行数和列数相等的矩阵,先给出一个数M,让算矩阵A的M次幂,A^M.在此只要求计算并不需要去深究这个矩阵到底是什么含义。则上面代码可以化为。

上面只是简单的计算矩阵的幂,大家会感觉很抽象,因为上述矩阵并没有具体的含义,
现在就举例说明矩阵快速幂在实际运用中的意义:
以最常见的斐波那契数列为例:众所周知:斐波那契数列递推公式为:
F[n] = F[n-1] + F[n-2]. 由f[0]=0,f[1]=1,可以递推后面的所有数。
在以前,我们会常常用for循环,这是最直接的算法。

矩阵快速幂可以解决形似斐波那契数列的拓展形式以及变形形式,并且能够解决当n比较大的时候,注意其中的推导过程

贴一个下午矩阵快速幂模板题目的代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef struct
{
    ll mp[10][10];
}node;
node ans,res;
const ll mod = 1000000000 + 7;
node mul(node A,node B)
{
    node tmp;
    //初始化临时矩阵,用于存放A * B的结果 
    for(int i = 1;i <= 2;i++)
    {
        for(int j = 1;j <= 2;j++)
        {
            tmp.mp[i][j]=0;
        }
    }
    //矩阵相乘并且返回 
    for(int i = 1;i <= 2;i++)
    {
        for(int j = 1;j <= 2;j++)
        {
            for(int k = 1;k <= 2;k++)
            {
                (tmp.mp[i][j] += A.mp[i][k] * B.mp[k][j] % mod) % mod; 
            }
        }
    }
    
    return tmp;
}

void quick_pow(ll n,ll m)
{
    //定义一个单位矩阵,因为单位矩阵乘以任何一个矩阵都是其矩阵本身 
    
    for(int i = 1;i <= 2;i++)
    {
        for(int j = 1;j <= 2;j++)
        {
            if(i == j) ans.mp[i][j] = 1;
            else ans.mp[i][j] = 0;
        }
    }
    
    while(m)
    {
        if(m & 1)
        {
            ans = mul(ans,res);
        }
        res = mul(res,res);
        m >>= 1;
    }
}

void pre()
{
    res.mp[1][1] = 3;
    res.mp[1][2] = (-1 + mod) % mod;
    res.mp[2][1] = 1;
    res.mp[2][2] = 0;
}

int T;
ll tmp;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&tmp);
        if(tmp == 1)
        {
            printf("1\n");
        }
        else if(tmp == 2)
        {
            printf("2\n");
        }
        else
        {
            pre();
            quick_pow(2,tmp - 2);
//            for(int i = 1;i <= 2;i++)
//            {
//                for(int j = 1;j <= 2 ;j++)
//                {
//                    printf("%lld ",ans.mp[i][j]);
//                }
//                printf("\n");
//            }
//            printf("---------------------------\n");
//            for(int i = 1;i <= 2;i++)
//            {
//                for(int j = 1;j <= 2 ;j++)
//                {
//                    printf("%d ",res.mp[i][j]);
//                }
//                printf("\n");
//            }
            ll final = ((ans.mp[1][1] * 2) % mod  + ans.mp[1][2]) % mod;
            printf("%lld\n",final);
        }
    }
    return 0;
}

注意矩阵快速幂的取模,如果存在矩阵系数是负数的时候要先在设置矩阵的时候进行取模,不然会因为各种原因爆掉

 

posted @ 2021-08-13 16:36  Treasure-  阅读(131)  评论(0)    收藏  举报