矩阵浅谈qwq
矩阵:
前置知识:
矩阵,定义太长了,其实就是个屑二维数组。(
他的运算也比较毒瘤。
- 加减法:
太屑了。
比如两个矩阵相加,其实就是对应位置加减去对应位置的数就行了。
- 乘除法:
乘法很毒瘤,但这就是定义,只有一个 和一个 的矩阵才能相乘,这里前后的顺序不能颠倒,因为这就是毒瘤定义,当且仅当一个矩阵的长等于另一个矩阵的宽才能乘。
乘完之后就乘了一个 的矩阵。
然后我们现在只知道这样能乘,和乘完之后成为一个什么样的矩阵,那里有的值是啥呢。
我们设一个矩阵 为一个 的矩阵,然后我们再设一个矩阵 为一个 的矩阵,我们由前面告诉你的毒瘤定义可知, 后的矩阵 为一个 的矩阵。
我们有以下公式可以求出矩阵中任意一个点的元素大小:
其实感觉有点像向量,虽然好像一点关系也没有。
- 数乘运算:
就是一个数乘一个 矩阵,这个时候你可能就要问了啊,那你把一个数看成一个 的矩阵,那这不就是不满足你的定义了吗。
这个时候我们跳出规则,把格局打开,再重新定义一手。
矩阵的数乘就是把这个数乘到每一个 元上
- 矩阵转置:
就是把一个矩阵旋转 。
这就是矩阵的一些基础前置知识,然后我们来讲矩阵快速幂。
- 单位矩阵
就相当于一个 , 主对角线上全为 ,其余地方为 的矩阵就是单位矩阵。
矩阵快速幂
这可是个好东西。
比如你要得出了一个递推式,奈何他让你递推 ,那你怎么办,那就用矩阵加速递推,那怎么加速递推呢,就用矩阵快速幂。
我们根据前面的定义知道一个 矩阵 是可以不断的乘自己的,就是不断的转置,然后乘。
我们想要求出 。
那该怎么求呢。
我们仿照快速幂的方法来求。
我们用一个结构体来存:
struct node { int a[MAXN][MAXN]; node() {memset(a, false, sizeof a);} void build() {for(int i = 1; i <= n; i++) a[i][i] = 1;} //构造单位矩阵 void print() { for(int i = 1; i <=n;cout << '\n', i++){ for(int j = 1; j <= n; j++) { cout << a[i][j] << " "; } } } }
应该没有人看不懂吧。
然后乘法就是仿照之前提到的式子模拟即可。
node operator * (const node &x, const node &y) { node z; for(int l = 1; l <= n; l++) { for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { z.a[i][j] = (z.a[i][j] + x.a[i][l] * y.a[l][j] % mod) % mod; } } } return z; }
就是我们 的矩阵。
然后具体求解的时候也就是 。
,
这里 是 , 就是 。
node ksm(node A, int k) { node res; res.build(); while(k) { if(k & 1) res = res * A; A = A * A, k >>= 1; } return res; }
然后我们就愉快的将模板题切掉了。
矩阵加速递推:
那什么样的递推式才能用矩阵加速递推呢,就是给你前几项,然后后面的等于前面某几项的和,要是按照递推式推过去会超时,这个时候就需要用到矩阵来加速递推了。
具体是怎么递推呢,我们需要构造两个矩阵,一个是初始矩阵,一个是递推矩阵,这个递推矩阵一般是一个 的矩阵。
比如我们的通项公式为 ,然后我们知道 ,如果我让你求 。
我们就用初始矩阵去乘上递推矩阵的 就能得到了。
那怎么去构造这两个矩阵呢。
画个图来感性理解一下 qwq
。
我们要求出第二个矩阵,观察一下这两个矩阵 和 相对,然后根据通项公式可知,,所以 。剩下的一个样。
最后我们求出来第二个矩阵 :
然后开始乘就行了,其实挺简单的。
代码贴贴:
struct node { int a[MAX][MAX]; node() {memset(a, false, sizeof a); } void build() { for(int i = 1; i <= 3; i++) a[i][i] = 1; } }Frist, t; node operator * (const node &x, const node &y) { node res; for(int i = 1; i <= 3; i++) { for(int k = 1; k <= 3; k++) { for(int j = 1; j <= 3; j++) { res.a[i][j] = (res.a[i][j] + x.a[i][k] * y.a[k][j] % mod) %mod; } } }return res; } node Ksm(node x, int k) { node res; res.build(); while(k) { if(k & 1) res = res * x; x = x * x, k >>= 1; }return res; } Frist.a[1][1] = Frist.a[1][2] = Frist.a[1][3] = 1; t.a[1][1] = t.a[1][2] = t.a[2][3] = t.a[3][1] = 1;
本文作者:TLE_Automation
本文链接:https://www.cnblogs.com/tttttttle/p/16293607.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现