矩阵相乘优化算法实现讲解

矩阵相乘

     什么是矩阵?

在数学中,矩阵(Matrix)是指纵横排列的二维数据表格,最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。

矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。并且在ACM竞赛,有很多涉及到矩阵知识的题。许多算法都会结合矩阵来处理,而比较具有代表性的矩阵算法有:矩阵快速幂、高斯消元等等。

例如下面的图片就是一个矩阵:

上述矩阵是一个 4 × 3 矩阵:

某矩阵 A 的第 i 行第 j 列,或 I , j位,通常记为 A[i,j] 或 Aij。在上述例子中 A[3,3]=2。

此外 Aij = (aij),意为 A[i,j] = aij

矩阵常用知识

①  矩阵相乘的规则:矩阵与矩阵相乘 第一个矩阵的列数必须等于第二个矩阵的行数 假如第一个是m*n的矩阵 第二个是n*p的矩阵 则结果就是m*p的矩阵 且得出来的矩阵中元素具有以下特点:

第一行第一列元素为第一个矩阵的第一行的每个元素和第二个矩阵的第一列的每个元素乘积的和 以此类推 第i行第j列的元素就是第一个矩阵的第i行的每个元素与第二个矩阵第j列的每个元素的乘积的和。

②  单位矩阵: n*n的矩阵  mat ( i , i )=1;  任何一个矩阵乘以单位矩阵就是它本身 n*单位矩阵=n, 可以把单位矩阵等价为整数1。(单位矩阵用在矩阵快速幂中)

例如下图就是一个7*7的单位矩阵:

矩阵相乘算法实现:

①  依据简单的矩阵相乘规则我们很容易写出代码:

for(int i=0;i<n;i++)

       for(int j=0;j<n;j++)

           for(int k=0;k<n;k++)

                t[i][j]=(t[i][j]+x[i][k]*y[k][j]);

这个代码就是简单的计算,按照计算规则,依次算出结果矩阵的每一位元素,就是一个一个的计算出所有元素。这种思路比较简单好想,但是这种算法的复杂度是O(N3),而且不能进行优化,所以在平时在进行矩阵乘法时使用起来往往会超时。

②  我们再看一种操作方法:

一行一行的计算出所有元素:

for(int i=0;i<n;i++)

       for(int k=0;k<n;k++)

           for(int j=0;j<n;j++)

                t[i][j]=(t[i][j]+x[i][k]*y[k][j]);

试想一下:什么情况下不用再进行相乘的操作?

其实就是一个数为0的时候,这时候即使相乘也不会改变原来位置上的值。

比如,如果此时X[i][k]的值为0,那你即使进行循环操作,t[i][j]值一样不会改变。所以,当x[i][j]值为0时,我们就没必要再进行相乘操作。这样的话就会优化一定的时间。而且这种优化对于一般算法要求的时间复杂度已经足够了。

优化后代码示例:

for(int i=0;i<n;i++)

       for(int k=0;k<n;k++)

                if(x[i][k])  //优化步骤 

           for(int j=0;j<n;j++)

               t[i][j]=(t[i][j]+x[i][k]*y[k][j]);

③  还有一种操作是一列一列的计算出所有元素:

这种情况下一样可以进行优化。

for(int j=0;j<n;j++) 

       for(int k=0;k<n;k++) 

                if(y[k][j])  //优化  

           for(int i=0;i<n;i++) 

               t[i][j]=(t[i][j]+x[i][k]*y[k][j]); 

算法模板:

void Matmul(LLX[MAXN][MAXN],LL Y[MAXN][MAXN])  

{ 

    LL t[MAXN][MAXN]={0}; 

    for(int i=0;i<N;i++) 

        for(int k=0;k<N;k++) 

            if(X[i][k]) 

            for(int j=0;j<N;j++) 

                t[i][j]=(t[i][j]+X[i][k]*Y[k][j]);

    for(int i=0;i<N;i++) 

        for(int j=0;j<N;j++)  

            X[i][j]=t[i][j]; 

} 

例题:

来源:HDOJ 4920 Matrixmultiplication

Problem Description

Given two matrices A and B of size n×n, find the product of them.

bobo hates big integers. So you are only asked to find the result modulo 3.

Input

The input consists of several tests. For each tests:

The first line contains n (1≤n≤800). Each of the following n lines contain n integers -- the description of the matrix A. The j-th integer in the i-th line equals Aij. The next n lines describe the matrix B in similar format (0≤Aij,Bij≤109).

Output

For each tests:

Print n lines. Each of them contain n integers -- the matrix A×B in similar format.

Sample Input

1
0
1
2
0 1
2 3
4 5
6 7

Sample Output

0
0 1
2 1

题目大意:求两个矩阵相乘mod3的结果。

这道题就是一个赤裸裸的矩阵相乘的题。但是要注意题目的时间复杂度,一定要进行优化。并且,此题还有二个坑点,如果把握不好就会超时。

①  就是Mod 3 时,一定不能在矩阵相乘算法的for循环里,如果放在相乘算法里会超时。

②在进行相乘之前把所有元素先Mod 3 这样做也会优化一定的时间。

因为题目所给数据并不是很大,所以即使把mod 3 放到结束输出语句里面就可以了,不用担心相乘的过程会超出int型。

AC代码:

   #include <stdio.h> 

   #include <string.h> 

   #include <algorithm> 

   using namespace std; 

   const int MAXN = 810; 

   const int Modn = 3; 

   int N; 

   int X[MAXN][MAXN]; 

   int Y[MAXN][MAXN]; 

   int t[MAXN][MAXN]; 

   int main() 

   { 

       while(scanf("%d",&N)!=EOF){ 

           for(int i=0;i<N;i++){ 

                for(int j=0;j<N;j++){ 

                   scanf("%d",&X[i][j]); 

                    X[i][j]%=3; 

                } 

           } 

           for(int i=0;i<N;i++){ 

                for(int j=0;j<N;j++){ 

                   scanf("%d",&Y[i][j]); 

                    Y[i][j]%=3; 

                    t[i][j]=0; 

                } 

           } 

           for(int i=0;i<N;i++){ 

                for(int k=0;k<N;k++) 

                    if(X[i][k]) 

                        for(intj=0;j<N;j++) 

                           t[i][j]=(t[i][j]+X[i][k]*Y[k][j]%3)%3; 

           } 

           for(int i=0;i<N;i++){ 

                printf("%d",t[i][0]); 

                for(int j=1;j<N;j++){ 

                    printf("%d",t[i][j]); 

                } 

                printf("\n"); 

           } 

       } 

       return 0; 

} 

单独考察矩阵相乘的题目并不多见,普遍都是结合矩阵快速幂,高斯消元等矩阵算法。进行这些算法之前我们必须要掌握矩阵相乘算法

我们需掌握简单的相乘规则,才能学习后面的一些矩阵算法。同时,为了以后学习算法以及做题的需要,我们也要记得矩阵相乘时的算法复杂度及优化细节。

版权声明:本文为博主原创文章,转载请注明出处。

时间: 2024-11-03 22:01:20

矩阵相乘优化算法实现讲解的相关文章

矩阵相乘的算法

很久没写blog了,感觉人都快变的抑郁了,换工作之后各种揪心,说好了是做Android的,结果让我搞各种算法,也罢,权当学习了一点知识吧. 今天说说矩阵相乘的算法,计算算法很简单,就是3个for循环. 首先还是说下矩阵相乘的概念,其实大学的时候线性代数中应该有讲到,不过到现在估计都还给老师了. 废话不多说,矩阵,其实就是一个二维数组,横竖排列的,比如int[5][6],就是一个矩阵,表示有5行6列. 只有当矩阵A的列数与矩阵B的行数相等时A×B才有意义.一个m×n的矩阵a(m,n)左乘一个n×p

hdu 4920 Matrix multiplication(矩阵相乘)多校训练第5场

Matrix multiplication                                                                           Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Given two matrices A and B of size n×n, find the

算法笔记_003:矩阵相乘问题【分治法】

目录 1 问题描述  1.1实验题目 1.2实验目的 1.3实验要求 2 解决方案 2.1 分治法原理简述 2.2 分治法求解矩阵相乘原理 2.3 具体实现源码 2.4 运算结果截图 1 问题描述 1.1实验题目 设M1和M2是两个n×n的矩阵,设计算法计算M1×M2 的乘积. 1.2实验目的 (1)提高应用蛮力法设计算法的技能: (2)深刻理解并掌握分治法的设计思想: (3)理解这样一个观点:用蛮力法设计的算法,一般来说,经过适度的努力后,都可以对其进行改进,以提高算法的效率. 1.3实验要求

C语言 &#183; 矩阵相乘 &#183; 算法提高

算法提高 矩阵相乘 时间限制:1.0s   内存限制:256.0MB 问题描述 小明最近在为线性代数而头疼,线性代数确实很抽象(也很无聊),可惜他的老师正在讲这矩阵乘法这一段内容. 当然,小明上课打瞌睡也没问题,但线性代数的习题可是很可怕的. 小明希望你来帮他完成这个任务. 现在给你一个ai行aj列的矩阵和一个bi行bj列的矩阵, 要你求出他们相乘的积(当然也是矩阵). (输入数据保证aj=bi,不需要判断) 输入格式 输入文件共有ai+bi+2行,并且输入的所有数为整数(long long范围

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 一:稀疏矩阵的三元组顺序表数据结构 typedef int ElemType; typedef struct { intx, y;  //该非零元素的行下标和列下标 ElemTypee; //该非零元素的值 } Triple; typedef struct { Tripledata[MAXSIZE]; //非零元素三元组顺序表 intmu, nu, t

用矩阵乘法优化递推

(有关矩阵乘法的基本规则请自行搜索) 引例:求斐波那契数列的第 n 项 mod 1000000007 的值,n <= 1018. 分析:斐波那契数列的递推式为 f(n) = f(n-1)+f(n-2),直接循环求出 f(n) 的时间复杂度是 O(n),对于题目中的数据范围显然无法承受.很明显我们需要对数级别的算法. 由于 f(n) = 1*f(n-1) + 1*f(n-2) 这样的形式很类似于矩阵的乘法,所以我们可以先把这个问题复杂化一下,将递推求解 f(n) 与 f(n-1) 的过程看作是某两

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

用Spark学习矩阵分解推荐算法

在矩阵分解在协同过滤推荐算法中的应用中,我们对矩阵分解在推荐算法中的应用原理做了总结,这里我们就从实践的角度来用Spark学习矩阵分解推荐算法. 1. Spark推荐算法概述 在Spark MLlib中,推荐算法这块只实现了基于矩阵分解的协同过滤推荐算法.而基于的算法是FunkSVD算法,即将m个用户和n个物品对应的评分矩阵M分解为两个低维的矩阵:$$M_{m \times n}=P_{m \times k}^TQ_{k \times n}$$ 其中k为分解成低维的维数,一般远比m和n小.如果大

深度解读最流行的优化算法:梯度下降

深度解读最流行的优化算法:梯度下降 By 机器之心2016年11月21日 15:08 梯度下降法,是当今最流行的优化(optimization)算法,亦是至今最常用的优化神经网络的方法.本文旨在让你对不同的优化梯度下降法的算法有一个直观认识,以帮助你使用这些算法.我们首先会考察梯度下降法的各种变体,然后会简要地总结在训练(神经网络或是机器学习算法)的过程中可能遇到的挑战.(本文的中文版 PDF 下载地址) 目录: 梯度下降的各种变体 批量梯度下降(Batch gradient descent)