矩阵(+ - *)
前言:用数组描述矩阵,下标可以从0开始,也可以从1开始,根据需要来定。
PS:矩阵的本质就是线性方程式!
下面我们来介绍几种矩阵类型:
N阶矩阵(同型矩阵):横纵个数相同
行矩阵:一行的那种
列矩阵:一列的那种
单位矩阵(高斯消元法中体现):如同乘法中的单位1(如下所示)
1 0 0
0 1 0
0 0 1
一、矩阵加法(必须是同型矩阵)
满足
a+b=b+a
(a+b)+c=a+(b+c)
例:
二、矩阵减法(同样必须是同型矩阵,基本上和矩阵加法相同)
本质就是矩阵的对应的位置相加减即可。是不是很容易呢?哈哈,别高兴,这只是一个开端......
三、矩阵乘法(必须是同型矩阵)
诡异的意义:
试想这样一个场景,你坐在空调屋里,吃着西瓜,玩着手机,你妈见状,非常无语,就让你下楼买酱油。
你领了钱,屁颠屁颠的踏上了一条“不归路”.......
走进一家商店,你发现这里的酱油搞促销,2块5瓶,1块3瓶,你决定采用矩阵的形式进行计算。
算完后你觉得不能在一条树上吊死,那就脚踏两条船吧!qwq.....
你去了隔壁老王家的店,老王不在家,只有他的儿子在店里,小王告诉你2块1瓶,3块2瓶,身为公认的小天才的你同样运用矩阵的形式进行计算。
计算后,你发现老王家的店太坑了,互为邻居也不便宜点儿,你气急败坏的转身欲走,这时老王回来了,你告诉了他小王的“所作所为”,老王大为头痛,并且告诉你,全都是泡沫,一切都是假象,你愤怒的告诉了老王第一家店的价钱,老王对你非常无语,因为第一家店正是老王家的分店,为了维护好邻里关系,老王决定,你可以根据这两家店的优惠活动来决策出一种最便宜的方案。身为小天才的你,轻松找到了最便宜的方案。看着小王拿酱油的身影,你身心畅快(毕竟剩下的钱你可以为所欲为)。
回到家后,你原以为你妈会表扬你的勤俭节约。但是母上大人却大发脾气,此时委屈的你发现带回来的竟然是——老陈醋!!!(真是日了狗了)
我们管这种从材料的数量及价格转换为总花费的过程叫做一个线性映射。
看到这里,相信你对矩阵乘法已经有了初步的一个认识。
矩阵乘法规则:
矩阵的第m行与第n列交叉位置的那个值,等于第一个矩阵第m行与第二个矩阵第n列,对应位置的每个值的乘积之和。
通俗点来讲就是: 第一个矩阵第一行的每个数字,各自乘以第二个矩阵第一列对应位置的数字,然后将乘积相加,得到的结果即为矩阵左上角的那个值。
为什么要这样计算呢?详细讲解:
http://www.ruanyifeng.com/blog/2015/09/matrix-multiplication.html
(毕竟这是关于数学上的证明,跟信息学本身并没有多大关系,可不掌握,记住结论即可)
让我们看一个完整的矩阵乘法计算吧!
因数交换一下可以吗?
答案是不可以!!矩阵乘法必须是第一个矩阵的行与第二个矩阵的列的乘积,上面的式子不满足这一点,所以错误。(只有两个矩阵相乘时)
所以乘法并不满足交换律~
又到了代码实现时间了,“铛铛铛铛”......
#include<iostream> using namespace std; int a[20][20],b[20][20],c[20][20]; int main() { int m,n,s; cin>>m>>s>>n; for(int i=0;i<m;i++) for(int j=0;j<s;j++) cin>>a[i][j]; for(int i=0;i<s;i++) for(int j=0;j<n;j++) cin>>b[i][j]; for(int i=0;i<m;i++) { for(int k=0;k<n;k++) { for(int j=0;j<s;j++) { c[i][k]+=a[i][j]*b[j][k]; } } } for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(j!=n-1) cout<<c[i][j]<<" "; else cout<<c[i][j]<<endl; } } return 0; }
三层for循环,你值得拥有!
PS;矩阵没有除法
矩阵快速幂推荐博客:
高斯消原法推荐博客:
https://blog.csdn.net/pengwill97/article/details/77200372(首推)
https://wenku.baidu.com/view/5b1ab0e40066+f5335b812188.html(几个注意事项,可以结合上下两个来看)
https://www.luogu.org/problemnew/solution/P3389(洛谷,上面有很多大佬讲的很详细)
Happy ending!
TIP
- 高斯消元法可以求得n元一次方程的解。
- 整数快速幂的时间复杂度是O(log2N),而矩阵快速幂的时间复杂度是O(log(n))
特别注意:
满足A(矩阵)为m×p,B(矩阵)为p×n才可以使用矩阵乘法。
附语:
矩阵的相关知识并不是很难,关键是要认真理解,代码不懂得地方手动模拟一遍就好了!
念念不忘,必有回响!
尾附矩阵快速幂和高斯消元法的代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; const int M = 1e9+7; struct Matrix { long long a[2][2]; Matrix() { memset(a, 0, sizeof(a)); } Matrix operator * (const Matrix y) { Matrix ans; for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) for(int k = 0; k <= 1; k++) ans.a[i][j] += a[i][k]*y.a[k][j]; for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) ans.a[i][j] %= M; return ans; } void operator = (const Matrix b) { for(int i = 0; i <= 1; i++) for(int j = 0; j <= 1; j++) a[i][j] = b.a[i][j]; } }; int solve(long long x) { Matrix ans, trs; ans.a[0][0] = ans.a[1][1] = 1; trs.a[0][0] = trs.a[1][0] = trs.a[0][1] = 1; while(x) { if(x&1) ans = ans*trs; trs = trs*trs; x >>= 1; } return ans.a[0][0]; } int main() { int n; scanf("%d", &n); cout << solve(n-1) << endl; return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; double a[110][110]; int n; int main() { scanf("%d",&n); for(int j=1;j<=n;j++) for(int i=1;i<=n+1;i++) scanf("%lf",&a[j][i]); for(int i=1;i<=n;i++)//i表示列数 { int mmax=i; for(int j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[mmax][i]))mmax=j; if(mmax!=i) for(int j=1;j<=n+1;j++) { swap(a[i][j],a[mmax][j]); } if(a[i][i]==0) { printf("No Solution\n"); return 0; } for(int j=i+1;j<=n+1;j++) { a[i][j]=a[i][j]/a[i][i]; } for(int j=1;j<=n;j++) if(j!=i) for(int z=i+1;z<=n+1;z++) a[j][z]-=a[i][z]*a[j][i]; } for(int i=1;i<=n;i++) printf("%.2lf\n",a[i][n+1]); return 0; }
完结撒花!