省选算法学习-矩阵与矩阵快速幂

0x00 引入

矩阵,顾名思义,就是由数构成的矩形阵列

比如这样的:$\begin{array}{l}\begin{bmatrix}2&3&4\0&7&13\c&\alpha&\sqrt5\end{bmatrix}\\end{array}$

就是一个3*3的矩阵

矩阵在信息学乃至数学里面的用处都非常广泛,下面就来介绍下它的一些基本知识,以及常用的地方。本文同时还会介绍矩阵快速幂以及快速矩阵乘法。

0x01 何为矩阵

矩阵的定义

其实就是上面那样的啦......

定义一个n行m列的矩阵为由n*m个数构成的矩形阵列,其中“数”可以是虚数、实数、01......

矩阵的定义实际上源于线性代数中的线性映射,但是这样定义实在是过于复杂,因此一般(包括高中数学)里面都用行列的方式定义矩阵

矩阵的基本运算

矩阵的基本运算包括加法和数乘

矩阵加法

矩阵加法定义在两个行数列数相同的矩阵之间

两个n*m矩阵相加得到一个n*m矩阵,其中得到的新矩阵每个位置上的元素等于原来的两个矩阵对应位置上的元素之和

例:

$\begin{bmatrix}2&4\5&3\8&1\end{bmatrix}+\begin{bmatrix}5&3\6&7\9&2\end{bmatrix}=\begin{bmatrix}7&7\11&10\17&3\end{bmatrix}$

矩阵加法满足交换律、结合律

矩阵减法类似,不赘述

矩阵数乘

矩阵数乘定义在一个矩阵和一个数之间

一个数和一个n*m矩阵数乘,得到一个n*m矩阵,新矩阵每一个元素等于旧矩阵对应元素乘上那个数

例:

$2\ast\begin{bmatrix}2&4\5&3\8&1\end{bmatrix}=\begin{bmatrix}4&8\10&6\16&2\end{bmatrix}$

矩阵数乘满足交换律(数之间交换)、结合律(只有一个矩阵的情况下),以及分配率(一个数乘两个矩阵或者一个矩阵乘两个数都可以)

矩阵乘法

矩阵乘法是一个大话题,值得单独拿出来讲一下

矩阵乘法最初的定义是线性代数中两个线性空间之间的两个映射的“乘积”,因为一个这样的线性映射可以用矩阵表示,那么两个映射(也就是A映射到B,B映射到C)就可以了乘起来表示

当然,这篇博客不会把线性代数拖出来讲;本文只会给出矩阵乘法的运算方法——因为它在OI中大有用途

两个矩阵A与B能够进行矩阵乘法运算(A*B),当且仅当A的列数和B的行数相同(因此矩阵乘法并不满足交换律)

设A是n*m的矩阵,B是m*k的矩阵,同时设A*B=C

那么:

C矩阵是n*k的,同时C矩阵的每一个元素的值如此计算:

$c\left[i\right]\left[j\right]={\textstyle\sum_{p=1}^m}a\left[i\right]\left[p\right]\ast b\left[p\right]\left[j\right]$

也就是说,新矩阵的第(i,j)个元素相当于A的第i行和B的第j列上每个元素一一相乘再求和,这也是为什么矩阵乘法要求列数行数相同

例:

$\begin{bmatrix}10&1\end{bmatrix}\ast\begin{bmatrix}a&0\c&1\end{bmatrix}=\begin{bmatrix}10a+c&1\end{bmatrix}$

矩阵乘法不满足交换律,但是满足结合律(仅限A*B*C这样的连续矩阵乘法)以及分配率(只要进行的都是合法运算)

矩阵乘法在OI中的主要应用

在OI中,矩阵乘法主要用于解决线性递推问题

线性递推就是这样的一类递推:

$h_n=\sum_{i=1}^{n-1}a_i h_i +b$

其中$h$是递推函数,$b$是常数项,$a_i$是系数(可以为零),且右式中的所有$h_i$的次数都是一

这时我们就可以用矩阵乘法来模拟转移了

例如斐波那契数列$f_{i+2}=f_i+f_{i+1}$

它的递推可以由这两个矩阵的乘法得到:

状态矩阵$\begin{bmatrix}f_i&f_{i+1}\end{bmatrix}$

转移矩阵$\begin{bmatrix}0&1\1&1\end{bmatrix}$

显然上述两个矩阵的矩阵乘积是$\begin{bmatrix}f_{i+1}&f_{i+2}\end{bmatrix}$

然而,这里有一个问题:矩阵乘法是$O\left(nmk\right)$的,明显比原来的时间效率要低啊,那为什么要这么做呢?

答案就是矩阵快速幂

矩阵的基础操作模板在此(没有数乘和加法的部分,因为OI中不常用也不常考,而且想必是很简单的)

struct ma{
    ll a[50][50],n,m;
    ma(){memset(a,0,sizeof(a));n=m=0;}
    void clear(){memset(a,0,sizeof(a));n=m=0;}
    const ma operator *(const ma &b){
        ma re;re.n=n;re.m=b.m;ll i,j,k;
        for(i=1;i<=n;i++){
            for(j=1;j<=b.m;j++){
                for(k=1;k<=m;k++){
                    re.a[i][j]+=a[i][k]*b.a[k][j];
                    re.a[i][j]%=MOD;
                }
            }
        }
        return re;
    }
    const void operator =(const ma &b){
        n=b.n;m=b.m;ll i,j;
        for(i=1;i<=n;i++) for(j=1;j<=m;j++) a[i][j]=b.a[i][j];
    }
};

0x02 矩阵快速幂

快速幂算法大家想必都很熟悉了:在$O\left(log_2 n\right)$的时间复杂度内求出一个数的n次方

那么,矩阵快速幂便是和它共同的

还是考虑斐波那契数列递推,我们发现,若设初始矩阵$\begin{bmatrix}f_1&f_2\end{bmatrix}$为$A$,而转移矩阵为$B$,那么我们要求的$f_n$就是这样得到的:

设矩阵$C=A\ast B^{n-1}$,那么显然C矩阵的第一行第二列的元素就是$f_n$的值

而由于矩阵乘法满足结合律,因此快速幂的思想在这里依旧可以使用,所以我们可以利用快速幂的思维,在很短的时间内把$B^{n-1}$求出来

那这个算法有什么优势呢?

当然是有的,比如我让你求斐波那契数列的第$10^{15}$项

此时矩阵快速幂就可以在$log 10^{15} \ast$ 矩阵乘法复杂度的时间内得出解,而这道题的矩阵乘法因为是1*2的矩阵乘2*2的,所以复杂度很低

矩阵快速幂的模板如下:

ma ppow(ma x,ma y,ll t){
    while(t){
        if(t&1) x=x*y;
        y=y*y;t>>=1;
    }
    return x;
}

是不是看起来非常像实数快速幂?实际上它们俩就是一样的

什么时候可以应用矩阵快速幂呢?

第一部分里我们说过,矩阵乘法可以用于解决线性递推问题

那么我们遇到有线性递推问题的时候,就可以方便地使用矩阵快速幂了

上面的斐波那契数列是一个例子,同时还有几个例题:

luoguP2044

luoguP1707

luoguP1357

可以看到,矩阵快速幂可以解决单个递推、多组递推、多组递推加上非线性常数的递推,甚至可以结合dp一起做,作为dp的优化

一般而言,我们都会构造一个一行k列的状态矩阵以及一个k行k列的转移矩阵

由于这种情况下新矩阵的每个格子互相独立,因此比较方便我们设计转移矩阵

在矩阵快速幂中,我们只要确定了状态矩阵和转移矩阵,那么问题一般就迎刃而解了

0x03 快速矩阵乘法

挖坑++......一周内补上

原文地址:https://www.cnblogs.com/dedicatus545/p/8684314.html

时间: 2024-11-03 15:55:52

省选算法学习-矩阵与矩阵快速幂的相关文章

算法学习笔记 递归之 快速幂、斐波那契矩阵加速

递归的定义 原文地址为:http://blog.csdn.net/thisinnocence 递归和迭代是编程中最为常用的基本技巧,而且递归常常比迭代更为简洁和强大.它的定义就是:直接或间接调用自身.经典问题有:幂运算.阶乘.组合数.斐波那契数列.汉诺塔等.其算法思想: 原问题可分解子问题(必要条件): 原与分解后的子问题相似(递归方程): 分解次数有限(子问题有穷): 最终问题可直接解决(递归边界): 对于递归的应用与优化,直接递归时要预估时空复杂度,以免出现用时过长或者栈溢出.优化递归就是以

矩阵乘法、快速幂

1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 // 矩阵的STL实现 7 typedef vector<int> vec; 8 typedef vector<vec> mat; 9 typedef long long ll; 10 const int MOD = 10

poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout

bzoj 3240 矩阵乘法+十进制快速幂

首先,构造出从f[][i]->f[][i+1]的转移矩阵a,和从f[i][m]->f[i+1][1]的转移矩阵b, 那么从f[1][1]转移到f[n][m]就是init*(a^(m-1)*b)^(n-1)*(a^(m-1)). 然后用用十进制快速幂(因为输入用的是10进制,这样就避免了高精度除法). 第一次写十进制快速幂,大概的思想是维护当前位是1-9的要乘的矩阵,然后再通过这9个矩阵自己转移. 1 /**********************************************

poj 3233 Matrix Power Series(矩阵二分,快速幂)

Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 15739   Accepted: 6724 Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + - + Ak. Input The input contains exactly one test cas

bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[i,j]=a*F[i][j-1]+

poj 3735 Training little cats(矩阵构造,快速幂)

Training little cats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10350   Accepted: 2471 Description Facer's pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make t

HDU 4365 正方形格子涂色中心对称轴对称的涂法有多少种-思维-(矩阵坐标关系&amp;快速幂取模)

题意:n*n的格子,涂色,有k种颜料,必须满足旋转任意个90度和翻转之后图片的样子不变,现在已经有m个格子涂过色了,问还有多少种涂法满足上述条件. 分析: 满足上述对称条件,那么涂色的种类问题我们可以放在正方形的一个角来做,因为一个角确定了其他角的颜色也就确定了. 以左上角的下半角为例.共有1+2+....+(n+1)/2个格子,然后记录涂过色的格子对应到这个三角形里的格子数目,用tot来记录,即每输入一个涂过色的格子的坐标我们就在这个三角形里找与之对应的坐标,用vis[][]数组标记是否已经计

省选算法学习-BSGS与exBSGS

前置知识 扩展欧几里得,快速幂 都是很基础的东西 扩展欧几里得 说实话这个东西我学了好几遍都没有懂,最近终于搞明白,可以考场现推了,故放到这里来加深印象 翡蜀定理 方程$ax+by=gcd(a,b)$一定有整数解 证明: 因为$gcd(a,b)=gcd(b,a$ $mod$ $b)$ 所以假设我们已经求出来了$bx+(a$ $mod$ $b)y=gcd(b,a$ $mod$ $b)$的一组整数解$(p,q)$ 因为$a$ $mod$ $b=a-(\lfloor \frac{a}{b} \rflo