寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄寄|

TLE_Automation

园龄:2年9个月粉丝:19关注:23

矩阵浅谈qwq

矩阵:

前置知识:

矩阵,定义太长了,其实就是个屑二维数组。(

他的运算也比较毒瘤。

  • 加减法:

太屑了。

比如两个矩阵相加,其实就是对应位置加减去对应位置的数就行了。

  • 乘除法:

乘法很毒瘤,但这就是定义,只有一个 a×b 和一个 b×c 的矩阵才能相乘,这里前后的顺序不能颠倒,因为这就是毒瘤定义,当且仅当一个矩阵的长等于另一个矩阵的宽才能乘。

乘完之后就乘了一个 a×c 的矩阵。

然后我们现在只知道这样能乘,和乘完之后成为一个什么样的矩阵,那里有的值是啥呢。

我们设一个矩阵 A 为一个 a×b 的矩阵,然后我们再设一个矩阵 B 为一个 b×c 的矩阵,我们由前面告诉你的毒瘤定义可知, A×B 后的矩阵 C 为一个 a×c 的矩阵。

我们有以下公式可以求出矩阵中任意一个点的元素大小:

Ci,j=r=1bAi,r×Br,j

其实感觉有点像向量,虽然好像一点关系也没有。

  • 数乘运算:

就是一个数乘一个 n×m 矩阵,这个时候你可能就要问了啊,那你把一个数看成一个 1×1 的矩阵,那这不就是不满足你的定义了吗。

这个时候我们跳出规则,把格局打开,再重新定义一手。

矩阵的数乘就是把这个数乘到每一个 (i,j) 元上

  • 矩阵转置:

就是把一个矩阵旋转 90o

这就是矩阵的一些基础前置知识,然后我们来讲矩阵快速幂。

  • 单位矩阵

就相当于一个 1, 主对角线上全为 1,其余地方为 0 的矩阵就是单位矩阵。

矩阵快速幂

这可是个好东西。

比如你要得出了一个递推式,奈何他让你递推 1018,那你怎么办,那就用矩阵加速递推,那怎么加速递推呢,就用矩阵快速幂。

我们根据前面的定义知道一个 n×m 矩阵 A 是可以不断的乘自己的,就是不断的转置,然后乘。

我们想要求出 Ak

那该怎么求呢。

我们仿照快速幂的方法来求。

我们用一个结构体来存:

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;
}

z 就是我们 x×y 的矩阵。


然后具体求解的时候也就是 Ak

这里 ansAkb 就是 A

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;
}

然后我们就愉快的将模板题切掉了。

矩阵加速递推:

那什么样的递推式才能用矩阵加速递推呢,就是给你前几项,然后后面的等于前面某几项的和,要是按照递推式推过去会超时,这个时候就需要用到矩阵来加速递推了。

具体是怎么递推呢,我们需要构造两个矩阵,一个是初始矩阵,一个是递推矩阵,这个递推矩阵一般是一个 3×3 的矩阵。

比如我们的通项公式为 ai=ai1+ai3,然后我们知道 a1,a2,a3,如果我让你求 a1e8

我们就用初始矩阵去乘上递推矩阵的 108 就能得到了。

那怎么去构造这两个矩阵呢。

画个图来感性理解一下 qwq

|ai1ai2ai3| × |zhbxjpssh| = |aiai1ai2|

我们要求出第二个矩阵,观察一下这两个矩阵 ai1ai 相对,然后根据通项公式可知,ai=ai1 + ai3,所以 z = 1 & x = 0 & s = 1。剩下的一个样。

最后我们求出来第二个矩阵 :

|110001100|

然后开始乘就行了,其实挺简单的。

代码贴贴:

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 中国大陆许可协议进行许可。

posted @   TLE_Automation  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起