线性代数学习笔记

文章介绍了矩阵的基本概念,如矩阵的加法、乘法和数乘,并强调了矩阵乘法的条件。接着,文章提到矩阵快速幂这一优化技巧,通过举例说明如何使用矩阵加速解决数列求解问题,如给定数列的递推关系,可以构建矩阵并利用快速幂计算数列的特定项,显著提高效率。此外,还给出了一个斐波那契数列的矩阵解法示例。
摘要由CSDN通过智能技术生成

线性代数学习笔记

矩阵(Matrix)

### 矩阵简介及矩阵加速

简介

在数学中,矩阵是一个按照长方阵列排列的复数或实数集合,最早来自于方程组的系数及常数所构成的方阵——百度百科

通俗的来讲,把集合里的一些数填入到一个矩形中即得到一个矩阵

定义

由​个数​排成的数表称为​行​列的矩阵简称​矩阵。

这​个数称为矩阵​的元素,简称为元。。。(剩下的都是百度百科的废话

有​行​列的矩阵也记作​

特别的,两个​都相同的矩阵称为同型矩阵

​的矩阵称为​阶矩阵或者​阶方阵

基本运算

加法

同时,矩阵的加法和实数的加法一样,满足交换律和结合律

应当注意,只有同型矩阵之间才可以进行加法

减法

在数集中,减法作为加法的逆运算

在矩阵中也是一样的

它也满足在实数集上的规律

数乘

在矩阵中引入了数乘的概念,即为一个数乘一个矩阵

矩阵的数乘满足以下规律:

乘法

两个矩阵的乘法仅当第一个矩阵​的列数和另一个矩阵​的行数相等时才能定义。

记作

也作

​的一个元素​的值为

例如

同时,矩阵的乘法满足以下运算律:

结合律:

左分配律:

右分配律:

矩阵加速

快速幂

这个还需要多说么?

int base=a,ans=1;
while(b>0){
    if(b&1){
        ans*=base
        ans%=c;
    }
    base*=base
    base%=c;
    b=b>>1;
}
return ans;

就是很简单的按位运算

所以我们对于一个矩阵的幂也可以这么来运算,于是时间复杂度从​降到了​

这就很舒服

但是这个有什么用呢?

例题一

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a数列的第n项对1000000007(10^9+7)取余的值。

第一眼看到这个题

?

这不是来送分的么

我一项一项去推不就好了???

对于100%的数据 T<=100,n<=2*10^9;

笑容逐渐凝固

所以现在就体现出矩阵加速的用处了

对于一个数列​

我们可以构造出一个​的矩阵表示当前的状态,即用​来表示我们当前已经知道的

然后我们再构造一个转移矩阵,使我们的原始矩阵乘上这个转移矩阵后可以变成一个新的矩阵,得到全新的​,从而一步步的向前推进,得到答案

显而易见,由于我们需要用到​和​,所以我们需要保留住这两个状态,​是由上个状态的​继承过来的,所以我们也需要保留,所以原始矩阵要构造成这个样子

即为

然后思考我们怎么由这个矩阵得到下一个矩阵

设我们当前矩阵为

我们希望得到的矩阵为

即为

显而易见我们的转移矩阵为

由于我们原始矩阵的第一项为​,所以我们只需要乘​次这个转移矩阵就可以得到了!

但是问题来了,这样不还是一个​的算法么?而且还慢了好多

当然不是!想一下我们矩阵乘法的结合律

我们设原始矩阵为​,转移矩阵为​,那么我们最终答案的矩阵就是

根据矩阵乘法的结合律,这个式子可以简化为

到了这里,我们就可以用矩阵快速幂来求出最终答案了!

​是真的快(

贴上我的巨丑无比的代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define mod 1000000007
using namespace std;
struct Ju{
    long long p[5][5];
    Ju operator *(const Ju &a)const{
        Ju c;
        for(long long i=1;i<=3;i++){
            for(long long j=1;j<=3;j++){
                c.p[i][j]=0;
            }
        }
        for(long long i=1;i<=3;i++){
            for(long long j=1;j<=3;j++){
                for(long long k=1;k<=3;k++){
                    c.p[i][j]+=(a.p[i][k]*p[k][j])%mod;
                    c.p[i][j]%=mod;
                }
            }
        }
        return c;
    }
}ans,base;
void build(){
    for(long long i=1;i<=3;i++){
        for(long long j=1;j<=3;j++){
            base.p[i][j]=0;
        }
    }
    base.p[1][1]=base.p[1][3]=base.p[2][1]=base.p[3][2]=1;
    ans.p[1][1]=ans.p[2][1]=ans.p[3][1]=1;
}
void qsm(long long p){
    while(p!=0){
        if(p&1){
            ans=ans*base;
        }
        base=base*base;
        p>>=1;
    }
}
long long T,n;
int main(){
    cin>>T;
    for(long long i=1;i<=T;i++){
        cin>>n;
        if(n<=3){
            printf("1\n");
            continue;
        }
        build();
        qsm(n-3);
        cout<<ans.p[1][1]<<endl;
    }
    return 0;
}

例题二

让你求斐波那契数列的第n项,数据范围是longlong级别的

很明显的矩阵加速

构造原始矩阵:

思考答案怎么由上一个状态转移过来

所以转移矩阵

下面就是简单的矩阵快速幂了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值