EVERYTHING HAPPENS FOR THE BEST!|

wnsyou

园龄:2年4个月粉丝:19关注:16

2023-08-05 11:51阅读: 104评论: 0推荐: 0

矩阵运算

矩阵运算

OI-wiki Link

众所周知,数是可以进行加减乘除的,那矩阵为啥不可以呢?

假设现在我们有两个矩阵 AB,矩阵大小分别为 n×mx×y,矩阵元素对 mod 取模。

const int N = 110, mod = 1e9 + 7; // 矩阵大小和模数
struct matrix {
int a[N][N], n, m; // 存储矩阵和矩阵大小
} ;

基本运算

矩阵加法

A+B=C

要求:n=x 并且 m=y

其实很简单,就是一一对应着加就行,即对于 1in,1jmCi,j=Ai,j+Bi,j

所以 C 的大小为 n×m,矩阵减法同。

性质

  • 交换律:明显满足,即 A+B=B+A
  • 结合律:明显满足,即 A+B+C=A+(B+C)

单位矩阵

明显,就是一个大小为 n×m 的全 0 矩阵。

矩阵加法 Code

时间复杂度:O(n×m)

matrix operator + (matrix y) { // 重载运算符 +
matrix z;
z.n = n, z.m = m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
z.a[i][j] = a[i][j] + y.a[i][j];
return z;
}

矩阵乘法

A×B=C

要求:m=x

公式:对于 1in,1jy:

Ci,j=1kmAi,k×Bk,j

似乎看起来没啥用?因为它是在某些特定方面可以进行时间优化(例如用 O(8logn) 的时间复杂度求出斐波那契数列的第 n 项),所以一般就是把它和其他知识点捆绑起来(例如矩阵乘法优化 dp 等),单独拎出来出的题目很少(大多都是板子)。

性质

  • 交换律:不满足!
    • n=y,交换以后还能乘法,但矩阵大小会变为 m×x,与原矩乘后答案不同。
    • 当然也有可能 ny,这样交换以后连矩乘的基本要求都无法满足。
  • 结合律:满足,设还有一个矩阵 C,大小为 y×zA×B×C=D,则 D 大小为 n×z,而 A×(B×C)=A×E(大小为x×z)=D
  • 分配律:明显满足,设还有一个矩阵 C,大小为 y×z,即 A×(B+C)=A×B+A×C

单位矩阵

Link

提到矩乘,就不得不提到它的单位矩阵。

单位矩阵定义:若这个矩阵乘任意一个矩阵 C,得到的结果都等于 C,则这个矩阵为单位矩阵。

观察式子,容易推出:当一个大小为 n×n 的矩阵除了主对角线(从左上到右下)以外的数为 1,其他都为 0 时,它就是一个可以作为所有大小为 n×m 的矩阵的单位矩阵。

时间复杂度:O(x×y)

void Clear (int x, int y, int f) { // 把矩阵大小设为 x * y,矩阵元素都为 f
n = x, m = y;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = f;
}
void Unit (int x, int y) { // 构造单位矩阵
Clear(x, y, 0); // 先清空
for (int i = 1; i <= n; i++)
a[i][i] = 1; // 只有主对角线为 1
}

矩阵乘法 Code

时间复杂度:O(n×m×y)

matrix operator * (matrix y) { // 重载运算符 *
matrix z;
z.n = n, z.m = y.m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= y.m; j++) {
z.a[i][j] = 0;
for (int k = 1; k <= m; k++)
z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod; // 套公式
}
return z;
}

矩阵除法

AB=C

要求:同矩阵乘法。

由于浮点数不可以取模,数里面除法取模等于乘上除数的逆,所以矩阵除法同矩阵除法,不过是把 Bi,j 变成 Bi,j 在模 mod 意义下的逆。

矩乘与它的特殊运算和应用

P3390 矩乘快速幂

给定一个矩阵 A,大小为 n×m,一个指数 k 和一个模数 mod,求 Ak % mod

要求:矩阵的大小必须为 n×n

既然矩乘有结合律,那么就可以考虑使用类似于整数快速幂的方法以 O(logk) 的方式求出 Ak,由于一次矩阵乘法需要 O(n3),所以总时间复杂度为 O(n3logk)

矩乘快速幂 Code

时间复杂度:O(n3logk)

matrix MATqmod (matrix x, ll y) { // 矩阵乘法快速幂
matrix sum;
sum.Unit(x.n, x.m); // 初始化为单位矩阵
while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1;
return sum;
}

P1349 广义斐波那契数列

P1962 斐波那契数列

广义的斐波那契数列是指形如 an=p×an1+q×an2 的数列。

今给定数列的两系数 pq,以及数列的最前两项 a1a2,另给出两个整数 nm,试求数列的第 nanmodm

Fi 表示当前情况下斐波那契数列第 i 项的值。

观察一下,把相邻两项构成一个矩阵,即要从 fi=[Fi,Fi1] 通过操作变为 fi+1=[Fi+1,Fi]=[p×Fi+q×Fi1,Fi],考虑用矩乘完成。

要能与 [Fi,Fi1] 做矩乘,就需要一个大小为 2×k 的矩阵,又因为矩乘之后的矩阵仍然大小为 1×2,所以 k=2,即要求一个矩阵 A=[a,bc,d],使得 A×fi=fi+1

套入公式,就是要求 {a×Fi+c×Fi1=p×Fi+q×Fi1b×Fi+d×Fi1=Fi,可以推出 {a=pb=1c=qd=0,现在要求 Fn,初始矩阵为[a2,a1],每次乘矩阵 A=[p,1q,0] 后都会使矩阵两项下标加 1,特判 n=1 的情况(答案为 a1),那么答案就是 [a2,a1]×An2 取第一个元素即可,需要矩阵乘法快速幂。

普通的其实就相当于 a1=a2=p=q=1

Code

matrix c, d;
int n, mod;
c.Clear(2, 2, 0), d.Clear(1, 2, 0);
cin >> c.a[1][1] >> c.a[2][1] >> d.a[1][2] >> d.a[1][1] >> n >> mod;
if (n == 1) {
cout << d.a[1][2];
return 0;
}
c.a[1][2] = 1, d = d * qmod(c, n - 2);
cout << d.a[1][1];

完整代码

点击查看最新代码
#include <bits/stdc++.h>
#define _1 (__int128)1
using namespace std;
using ll = long long;
void FileIO (string s) {
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
const int mod = 1e9 + 7, MATsize = 110; // 矩阵大小和模数
struct matrix {
int a[MATsize][MATsize], n, m; // 存储矩阵和矩阵大小
void Clear (int x, int y, int f) { // 把矩阵大小设为 x * y,矩阵元素都为 f
n = x, m = y;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = f;
}
void Unit (int x, int y) { // 构造单位矩阵
Clear(x, y, 0); // 先清空
for (int i = 1; i <= n; i++)
a[i][i] = 1; // 只有主对角线为 1
}
matrix operator + (matrix y) { // 重载运算符 +
matrix z;
z.n = n, z.m = m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
z.a[i][j] = a[i][j] + y.a[i][j];
return z;
}
matrix operator * (matrix y) { // 重载运算符 *
matrix z;
z.n = n, z.m = y.m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= y.m; j++) {
z.a[i][j] = 0;
for (int k = 1; k <= m; k++)
z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod; // 套公式
}
return z;
}
} ;
matrix MATqmod (matrix x, ll y) { // 矩阵乘法快速幂
matrix sum;
sum.Unit(x.n, x.m); // 初始化为单位矩阵
while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1;
return sum;
}
signed main () {
ios::sync_with_stdio(0), cin.tie(0);
// FileIO("");
return 0;
}
点击查看无注释代码
#include <bits/stdc++.h>
#define _1 (__int128)1
using namespace std;
using ll = long long;
void FileIO (string s) {
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
const int mod = 1e9 + 7, MATsize = 110;
struct matrix {
int a[MATsize][MATsize], n, m;
void Clear (int x, int y, int f) {
n = x, m = y;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = f;
}
void Unit (int x, int y) {
Clear(x, y, 0);
for (int i = 1; i <= n; i++)
a[i][i] = 1;
}
matrix operator + (matrix y) {
matrix z;
z.n = n, z.m = m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
z.a[i][j] = a[i][j] + y.a[i][j];
return z;
}
matrix operator * (matrix y) {
matrix z;
z.n = n, z.m = y.m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= y.m; j++) {
z.a[i][j] = 0;
for (int k = 1; k <= m; k++)
z.a[i][j] = (z.a[i][j] + 1ll * a[i][k] * y.a[k][j] % mod) % mod;
}
return z;
}
} ;
matrix MATqmod (matrix x, ll y) {
matrix sum;
sum.Unit(x.n, x.m);
while (y) sum = (y & 1 ? sum * x : sum), x = x * x, y >>= 1;
return sum;
}
signed main () {
ios::sync_with_stdio(0), cin.tie(0);
// FileIO("");
return 0;
}

本文作者:wnsyou

本文链接:https://www.cnblogs.com/wnsyou-blog/p/matrix.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wnsyou  阅读(104)  评论(0编辑  收藏  举报
  1. 1 勝利への道 安藤浩和
  2. 2 Minecraft’s End Eric Fullerton
  3. 3 月光曲完整版 贝多芬 云熙音乐
  4. 4 平凡之路 (Live版) 朴树
  5. 5 Minecraft C418
  6. 6 Paradise NiziU
  7. 7 叫我,灰原哀 龙大人不喷火
  8. 8 心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
  9. 9 战 歌 此去经年
心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 - 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 一殇/白祺/苏少安/苏栗无/公子无央/白刃昏鸦/非欢/清茗/未及昭声/汀帆/赵艹地

作曲 : 沐若

心机之蛙,一直摸你肚子

——《名侦探柯南》原创同人曲

策划:炊饭

作曲:沐若

作词:一殇、白祺、苏少安、苏栗无、公子无央、白刃昏鸦、非欢、清茗、未及昭声、汀帆、赵艹地

编曲:斓音音乐实验室

演唱:叶辞樱、温海、寒砧、南柯、小茜玛姬、墨催、阿崔Ac、贝壳初、千湛、兮茶子、乔慕、黎鹿北、起千温卿、遮阳伞、曲悠

后期:幽谷

题字/美工:徒夫

监制:楠烛

【角色-词作-歌手】

【铃木园子-一殇-叶辞樱】

没有绝对杀机

爱恨调转 对错是唯一

【赤井秀一-白祺-温海】

枪膛里银色子弹

最后的致命一击

-

【毛利小五郎-苏少安-寒砧】

沉睡倒看真相 别小瞧绅士

叼烟来探 糊涂作势

【妃英理-白祺-南柯】

剥离出实情

透过谎言再续 不败传奇

-

【苏栗无-樱/砧/海/柯】

迷茫中看见吗 向谁的真谛

让谁的眼泪 都变成迷离

罪的答案是你 路的尽头是你

-

【怪盗基德-公子无央-小茜玛姬】

Kaitou 这雪白的谜语 将帽檐压低

以滑翔翼敬礼 向手铐和你

【服部平次-白刃昏鸦-墨催】

爱与真相是唯一

十字路口 迷宫的暗语

-

【灰原哀-非欢-乔慕】

回到少年时期 退化至逃离

像天才的过去 深海的鲨鱼

【毛利兰-非欢-起千温卿】

害怕妖怪和雷雨

正义和你 是我的勇气

-

【清茗-姬/催/慕/卿/悠】

天才与罪犯在探试 我已锁定案件起始

黑暗中蛰伏无休止 被贪欲吞噬

黄昏时 布谷钟请柬送至

跋涉深渊之池 侦探们的镇魂诗

-

【目暮十三-一殇-阿崔Ac】

樱花之名起誓

追寻真相 对罪恶通缉

【阿笠博士-苏少安-贝壳初】

古怪是科学正义

热衷将永不歇止

-

【安室透-白刃昏鸦-千湛】

被隐去的名姓 真伪皆归零

谜面重启 逆向独行

【琴酒-未及昭声-兮茶子】

用死亡美学 虔诚将你献祭

无声狙击

-

【汀帆-崔/初/湛/茶】

拨开重重迷题 信仰即期许

平扫僵阵地 守一方境域

且看如何踏破 早已残废终局

-

【江户川柯南-未及昭声-黎鹿北】

真相 折射在那镜片 透视在眼底

借时间逆行 拆穿真凶伏笔

【工藤新一-公子无央-遮阳伞】

骄傲是天才之理

逐一剖析 黑色的缝隙

-

【赵艹地-鹿/伞】

转动命运齿轮 去超越世纪

继续探查疑案 来解开谜题

【贝尔摩德-赵艹地-曲悠】

最喜爱伪装神秘

卷入迷雾 从容扣动扳机

-终-

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示