矩阵的c++实现

news2025/2/22 12:20:25

在大学数学课程《线性代数》中,就有矩阵和行列式的出现,这篇文章主要讲矩阵在c++中的实现和一些用途(目前我知道的)

此篇文章只写c++的内容,不具体写到数学中矩阵的一些公式、性质。

本篇文章中一部分图片来自百度百科。

注:在编程中,习惯(不知道是不是只有我的习惯)写成n行m列矩阵,但在数学课本中,是m行n列的矩阵,不要搞混了

一、矩阵是什么

由 n×m 个数aij排成的n行m列的数表称为n行m列的矩阵,简称n×m矩阵。记作:

A=\begin{bmatrix} a11,a12,a13,...,a1m \\ a21,a22,a23,...,a2m \\ a31,a32,a33,...,a3m \\ ...,...,...,...,... \\ an1,an2,an3,...,anm \end{bmatrix}

第一次用公式不会用

二、构建一个矩阵

#include<bits/stdc++.h>
#define maxn 100 
using namespace std;
struct Matrix{
	int n,m;//n行m列矩阵 
	long long a[maxn][maxn];
	Matrix(){
		memset(a,0,sizeof a);
	}
	Matrix(int _n, int _m) {
        n=_n;
        m=_m;
        memset(a,0,sizeof a);
    }
    void scan(){
    	cin>>n>>m;
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cin>>a[i][j];
			}
		}
	}
	void print(){
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cout<<a[i][j]<<" ";
			}
			cout<<endl;
		}
	}
};
int main(){
	Matrix a;
	a.scan();
	a.print();
	return 0;
} 

非常简单

三、矩阵的运算

1.加法

只有m和n都相同的矩阵才可以相加。

设C=A+B,则:

Cij=Aij+Bij

矩阵加法满足交换律和结合律:

A+B=B+A

A+(B+C)=(A+B)+C

代码:

Matrix pl(Matrix a,Matrix b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]+=b.ma[i][j];
		}
	}
	return a;
}
int main(){
	Matrix a,b;
	a.scan();
	b.scan();
	pl(a,b).print();
	return 0;
} 

因为a会和矩阵里面的a长得很像,我就改了

2.数乘

就是将一个矩阵乘以一个数字

Matrix mul_num(Matrix a,int b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]*=b;
		}
	}
	return a;
}

满足以下定律:

结合律:a(bA)=(ab)A

交换律:aA=Aa

分配律:(a+b)A=aA+bA

              (A+B)a=aA+aB

好了,新手期度过

3.矩阵乘法

当A*B时,必须满足A的n(列数)和B的m(行数)相同。当A为p*n矩阵,B为n*q矩阵时,C为p*q矩阵。

他的元素:

Matrix mul(Matrix a,Matrix b){
	Matrix res(a.n,b.m);
	for(int i=0;i<a.n;i++){
		for(int j=0;j<b.m;j++){
			for(int k=0;k<a.m;k++){
				res.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
			}
		}
	}
	return res;
}

矩阵乘法满足的运算定律:

结合律:A(BC)=(AB)C

左分配律:C(A+B)=CA+CB

右分配律:(A+B)C=AC+BC

4.单位矩阵

我们都知道,1*a=a,那么如果我们要在矩阵中找到一个和1的性质一样的矩阵,要怎么做呢???

单位矩阵出场!

单位矩阵:一个n*n的矩阵,左下角到右下角都是1,其他都是0。

当n*m的矩阵乘以一个n*n的单位矩阵时,不会发生改变。

具体过程如下:

\begin{bmatrix} 2,3\\ 5,6\\ 4,3 \end{bmatrix}\times \begin{bmatrix} 1 ,0 \\ 0,1 \end{bmatrix}=\begin{bmatrix} 2\times1+0,3\times1+0 \\ 5\times1+0,6\times1+0 \\ 4\times1+0,3\times1+0 \end{bmatrix}

单位矩阵在快速幂中有用

5.矩阵快速幂

只有n*n矩阵才可以快速幂。

如何快速幂???

矩阵的快速幂和普通的不同,我们可以这样想:

A^7=A*A*A*A*A*A*A=(A*A)*(A*A)*A*A*A

说起来有些奇妙,但实际上就是个这样的过程:

Matrix mpow(Matrix a,int n){
	Matrix res(a.n,a.n);
	for(int i=0;i<res.n;i++)res.ma[i][i]=1;
    while(n!=0){
        if(n&1)res=mul(res,a);
        a=mul(a,a);
        n>>=1;
    }
    return res;
}

你可能看不懂,但如果我把他变成数字的快速幂,你就懂了。

int mpow(int a,int n){
	int res=1;//初始化
    while(n!=0){
        if(n&1)res=a*res;//统计多出来的a
        a=a*a;
        n>>=1;//就是除2
    }
    return res;
}

我们刚开始构建一个单位矩阵res,用他充当1的作用。

6.所有运算的代码

#include<bits/stdc++.h>
#define maxn 100 
using namespace std;
int mm;
struct Matrix{
	int n,m;
	long long ma[maxn][maxn];
	Matrix(){
		memset(ma,0,sizeof ma);
	}
	Matrix(int _n, int _m) {
        n=_n;
        m=_m;
        memset(ma,0,sizeof ma);
    }
    void scan(){
    	cin>>n>>m;
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cin>>ma[i][j];
			}
		}
	}
	void print(){
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cout<<ma[i][j]<<" ";
			}
			cout<<endl;
		}
	}
};
Matrix pl(Matrix a,Matrix b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]+=b.ma[i][j];
		}
	}
	return a;
}
Matrix mul_num(Matrix a,int b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]*=b;
		}
	}
	return a;
}
Matrix mul(Matrix a,Matrix b){
	Matrix res(a.n,b.m);
	for(int i=0;i<a.n;i++){
		for(int j=0;j<b.m;j++){
			for(int k=0;k<a.m;k++){
				res.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
			}
		}
	}
	return res;
}
Matrix mpow(Matrix a,int n){
	Matrix res(a.n,a.n);
	for(int i=0;i<res.n;i++)res.ma[i][i]=1;
    while(n!=0){
        if(n&1)res=mul(res,a);
        a=mul(a,a);
        n>>=1;
    }
    return res;
}
int main(){
	return 0;
} 

四、矩阵在编程中的运用

既然我们说了这么多,你可能会很疑惑:为什么我们要用到矩阵呢?编程中哪里需要用到矩阵呢?

我学矩阵时也这样,好像矩阵离我很远的样子。

那么我们来看几道例题:

1.洛谷P1962斐波那契数列

这道题用矩阵解很简单,有两种相似的做法。

第一种做法

我们都知道,斐波那契数列的式子是:

F_{n}=F_{n-1}+F_{n-2}

那我们考虑行矩阵

\begin{bmatrix} F_{n},F_{n-1} \end{bmatrix} =\begin{bmatrix} F_{n-1},F_{n-2}\end{bmatrix}\times base

那我们就要考虑base是什么

分解:

[F_{n},F_{n-1}]=[F_{n-1}+F_{n-1},F_{n-1}]

=[1\times F_{n-1}+1\times F_{n-2},1\times F_{n-1}+0\times F_{n-2}]

=[F_{n-1},F_{n-2}]\times \begin{bmatrix} 1,1\\ 1,0\\ \end{bmatrix}

这不就巧了吗,刚好就出现了n-1项和n-2项,那么base就是这个1110了

根据左分配律,可以得出,我们不断递推,就相当于

[1,1]\times base^{n-2}

多思考一下就可以得出了

那么,最后只要输出就行了

代码如下

#include<bits/stdc++.h>
#define maxn 100 
using namespace std;
int mm;
struct Matrix{
	int n,m;
	long long ma[maxn][maxn];
	Matrix(){
		memset(ma,0,sizeof ma);
	}
	Matrix(int _n, int _m) {
        n=_n;
        m=_m;
        memset(ma,0,sizeof ma);
    }
    void scan(){
    	cin>>n>>m;
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cin>>ma[i][j];
			}
		}
	}
	void print(){
    	for(int i=0;i<n;i++){
    		for(int j=0;j<m;j++){
    			cout<<ma[i][j]<<" ";
			}
			cout<<endl;
		}
	}
};
Matrix pl(Matrix a,Matrix b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]+=b.ma[i][j];
		}
	}
	return a;
}
Matrix mul_num(Matrix a,int b){
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			a.ma[i][j]*=b;
		}
	}
	return a;
}
Matrix mul(Matrix a,Matrix b){
	Matrix res(a.n,b.m);
	for(int i=0;i<a.n;i++){
		for(int j=0;j<b.m;j++){
			for(int k=0;k<a.m;k++){
				res.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
			}
		}
	}
	return res;
}
Matrix mpow(Matrix a,int n){
	Matrix res(a.n,a.n);
	for(int i=0;i<res.n;i++)res.ma[i][i]=1;
    while(n!=0){
        if(n&1)res=mul(res,a);
        a=mul(a,a);
        n>>=1;
    }
    return res;
}
int main(){
	return 0;
} 

第二种做法

我们换成竖的:

\begin{bmatrix} F_{n}\\ F_{n-1}\\ \end{bmatrix}

理论差不多,不多说了。不然又浪费我的手和时间

应该都会了吧,自己推吧,直接上代码(因为是上课写的,格式有些不一样)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
int mod;
typedef long long ll;
struct Matrix {
    int n, m;
    long long a[maxn][maxn];
    Matrix() { memset(a, 0, sizeof a); }
    Matrix(int _n, int _m) {
        n = _n;
        m = _m;
        memset(a, 0, sizeof a);
    }
};
Matrix mul(Matrix &a, Matrix &b) {
    Matrix res(a.n, b.m);
    for(int i=0;i<a.n;i++)
        for(int j=0;j<b.m;j++)
            for(int k=0;k<a.m;k++)
                res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
    return res;
}
Matrix Pow(Matrix &base, ll n) {
    Matrix res(base.n, base.n);
    for(int i=0;i<res.n;i++)res.a[i][i]=1;
    while(n!=0){
        if(n&1)res=mul(res,base);
        base=mul(base,base);
        n>>=1;
    }
    return res;
}
int main() {
    freopen("Fibonacci.in", "r", stdin);
    freopen("Fibonacci.out", "w", stdout);
    ll n;
    scanf("%lld%d", &n, &mod);
    if (n == 1 || n == 2) return 0 * puts("1");
    Matrix F(1,2);
    F.a[0][0]=1;
    Matrix A(2,2);
    A.a[0][0]=1;
    A.a[0][1]=1;
    A.a[1][0]=1;
    A.a[1][1]=0;
    A=Pow(A,n-1);
    F=mul(F,A);
    cout<<F.a[0][0];
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1035207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 12,调用系统库libft2.so 遇到的各种问题记录

问题前提,Android 12系统,vendor静态库中调用 libft2.so。(vendor静态库中调用libft2.so会简单点,没这么麻烦) 【问题1】 (native:vendor) can not link against libft2 (native:platform) 本地debug尝试修改: 为了本地环境debug调试方便,我找了个 mk文件,在里面添加了…

《富足》—没有完善的个人,但是可以有完善的团队

摘要&#xff1a;在吴军老师《富足》一书上&#xff0c;阅读到一句话&#xff1a;“没有完善的个人&#xff0c;但是可以有完善的团队”。很认同这句&#xff0c;目前听见最多的可能是“没有完美的个人&#xff0c;只有完美的团队”&#xff0c;这句长挂在嘴边的话在社会工作多…

Win7开启触摸键盘方法

在Win7系统中&#xff0c;自带有触摸屏幕键盘&#xff0c;能够在屏幕上显示虚拟键盘&#xff0c;让用户可以用指针设备或触屏等进行输入操作&#xff0c;那么Win7系统怎么开启触摸键盘呢&#xff1f;想知道的小伙伴可以跟着我一起来学习一下。 1、首先打开Win7系统的开始菜单&a…

计算机竞赛 深度学习YOLO抽烟行为检测 - python opencv

文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习YOLO抽烟行为检测 该项目较为新颖&#xff0c;适合作为竞赛课…

方案:TSINGSEE青犀智能分析AI皮带撕裂算法的场景应用

在工地矿山等现实场景中&#xff0c;皮带运输在生产过程中是必不可少的&#xff0c;然而&#xff0c;由于长时间高强度的运转&#xff0c;皮带很容易发生撕裂、破损、跑偏等问题。这些问题会严重影响生产速度&#xff0c;甚至会导致严重的安全事故。为了有效预防此类安全事故发…

windows server 2019 、2012等服务器查看系统和应用程序日志

查看windows系统日志 点击左下角的windows按钮&#xff0c;输入事件两个字&#xff0c;会显示时间查看器 点击事件查看器&#xff0c;windows日志下面可以卡到系统日志和应用程序的日志 筛选时间范围内的日志 修改记录时间 选组自定义范围 选择事件事件 输入事件范围&#xff…

功能安全Part1-名词定义

半年多没搞FuSa&#xff0c;好多名词已经忘了啥意思&#xff0c;总结一下。 Part1总共为FuSa定义了184个名词。这里捡下重要的描述下。 3.3 ASIL decomposition ASIL分解&#xff1a;将安全要求冗余地分配给充分独立的要素 &#xff08;这里指系统组件[软件或者硬件]&#xff…

思源笔记-S3协议多电脑同步教程

获取数据仓库密钥 ​ ​ 首次使用可能需要先创建,然后这个密钥用于你的其他电脑的思源笔记导入这个密钥才能多个电脑使用一个同步服务(S3协议) 如下图所示,你的另一台电脑就需要导入密钥​ ​ ​ 获取S3协议的服务 如图打开思源笔记的设置 ​ ​ 然后进入云端​​ ​…

Windows安装Mysql--免安装版

在Windows系统上安装免安装版MySql的步骤 官方下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 将下载好的文件“mysql-5.7.18-winx64”解压缩到C盘的 目录下&#xff1a; 配置环境变量&#xff1a; &#xff08;略&#xff09; 正式安装&#xff0c;添加my.i…

Linux下的网络编程——C/S模型 UDP(三)

前言&#xff1a; UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是一种在计算机网络中常用的传输层协议。与TCP&#xff08;传输控制协议&#xff09;相比&#xff0c;UDP是一种无连接的协议&#xff0c;不具备可靠性和流量控制等特性&#x…

Win11蓝牙无法连接怎么办?可以试试这个方法。

蓝牙对我们电脑来说还是较为重要的一项功能&#xff0c;如果蓝牙无法连接&#xff0c;会导致很多依靠蓝牙的设备&#xff0c;如蓝牙鼠标&#xff0c;蓝牙耳机等配合电脑使用的设备无法使用&#xff0c;给我们带来不少困扰&#xff0c;遇到这种情况的时候&#xff0c;可以试试下…

c语言 static

1、静态局部变量在程序加载时初始化&#xff0c;静态局部变量的初始值写入到了data段&#xff1a; 如下代码test_symbol.c int f() {static int x 0;return x; }int g() {static int x 9;return x; }使用命令gcc -c test_symbol.c -o test_symbol 编译 使用命令 readelf -a …

LaTex打出上大下小的公式

想要在latex中打出如下word公式 首先使用 \atop符号 使用如下语句 d_{H(A,B)} max\{{sup\, inf \atop {a \in A\,b \in B}}\,d(a,b), {sup\, inf\,\atop {b\in B\,a\in\,A}}d(b,a)\}. ![在这里插入图片描述](https://img-blog.csdnimg.cn/0c842594716a4693b1124523d53bfcad…

k8s 集群 -4 pod生命周期

首先 容器环境初始化,pod 由pod 镜像来提供 在pod 生命周期里 容器主要 分文两种&#xff1a;初始化容器和主容器 初始化 容器一定要成功运行并退出&#xff0c;当初始化容器运行退出完了之后 主容器开始和运行 主容器开始运行的时候 有两个探针 存活探针和就绪探针 Pod 可…

Docker实战技巧(二):Kubernetes基础操作实战

Kubernetes定位在Saas层,重点解决了微服务大规模部署时的服务编排问题 1、关闭防火墙并设置开机禁用   systemctl stop firewalld   systemctl disable firewalld 2、配置repo   cd /etc/yum.repos.d/   下载Docker repo   wget https://mirrors.aliyun.com/docker-…

【论文写作】Latex 所有符号汇总参考

【论文写作】Latex 所有符号汇总参考 文章目录 【论文写作】Latex 所有符号汇总参考1. 希腊字母2. 数学构造3. 分割4. 累加累成等5. 标准函数名称6. 二进制符号&#xff08;关系符号&#xff09;7. 箭头8. 杂项符号&#xff08;其他的符号&#xff09;9. 数学模式重音、音节10.…

结构体-寻找爱好相同的人

任务描述 每个人有三项爱好&#xff0c;分别是食物&#xff0c;饮料&#xff0c;电影&#xff0c;运动等中的任意三项&#xff0c;第 i 个人的三种爱好分别用一个整数 ai​&#xff0c;bi​&#xff0c;ci​ 来表示。现在给出 n 个人的爱好&#xff0c;如果两个人起码有两项以…

YOLOv3模型原理深度解析

概况 &#xff08;1&#xff09;YOLOv3是YOLO系列第一次引入残差连接来解决深度网络中的梯度消失问题&#xff08;是不是第一次&#xff0c;有待你后面考证&#xff09;&#xff0c;实际用的backbone是DarkNet53 &#xff08;2&#xff09;最显著的改进&#xff0c;也是对你涨…

[Linux]线程概念

[Linux]线程概念 文章目录 [Linux]线程概念什么是线程Linux系统下的线程实现线程是CPU调度的基本单位进程是系统分配资源的基本实体二级页表 线程的优点线程的缺点线程异常线程用途线程资源 什么是线程 线程是进程内部的一个执行分支&#xff0c;执行粒度比进程更细&#xff0…

MyBatis 中的插件可以拦截哪些操作

MyBatis 中的插件可以拦截哪些操作 MyBatis 是一个优秀的持久化框架&#xff0c;在实际项目开发中广泛应用。MyBatis 的插件机制可以方便地对 MyBatis 的各个环节进行扩展和定制。在本文中&#xff0c;我们将详细介绍 MyBatis 中的插件机制&#xff0c;并探讨插件可以拦截哪些…