线性代数里一个很重要的概念就是矩阵 ,在解算法题中矩阵也有很大的用处,比如说二维前缀和矩阵。
而矩阵里比较难以实现的一种运算法则就是矩阵的乘法,涉及乘法也必然涉及幂的问题。下面就有一种实现矩阵乘法和矩阵快速幂的方法。
首先我们先来看一下矩阵乘法的定义:
设A为 的矩阵,B为 的矩阵,那么称 的矩阵C为矩阵A与B的乘积,记作 ,其中矩阵C中的第
行第 列元素可以表示为:
简单记忆为:前列等后行(可以相乘的条件),前行乘后列(这代表了矩阵的大小,也代表对于每个aij,i行与j列分别对应相乘再相加)。
既然我们要用到快速幂,众所周知我们要先定义一个初始值为1的接收答案的变量,那么我们怎么去找这样一个“1”去接收矩阵的乘积呢?答案就是—符合乘法条件的单位矩阵。什么是单位矩阵?
如上图,主对角线元素全为1,且其他位置的元素全是0的矩阵叫做单位矩阵,任何矩阵乘以这种单位矩阵都是它自身。
还有一个小操作是重载运算符,这个操作的意义是给某个运算符赋予一个新的意义,一般格式如下:
bool opreator (sign) (datatype name, datatype name)
{
function body;
}
下面来看一下详细的实现代码
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld",&a)
#define din(a) scanf("%d",&a)
#define reset(a,b) memset(a,b,sizeof(a))
const int INF=0x3f3f3f3f;
using namespace std;
typedef long long ll;
typedef long double ld;
/*Although there will be many obstructs ahead of you,
the desire for victory still fills you with determination..*/
typedef struct
{
int mat[50][50];
int n,m;
} matrix;
//由于二维数组传递参数有限制(必须确定列数),所以我们把它放在结构体里。
matrix ma,mb,mc;
matrix multipy(matrix a, matrix b)//矩阵乘法
//重载运算符式写法:bool opreator *(matrix a,matrix b)
{
matrix ans;
reset(ans.mat,0);//!!!!必须清空这个临时矩阵
if(a.m==b.n)//前矩阵的列等于后矩阵的行乘法才有意义。
{
ans.n=a.n,ans.m=b.m;//确定大小
for(int i=1; i<=a.n; i++)
for(int j=1; j<=b.m; j++)
{
for(int k=1; k<=a.m; k++)
ans.mat[i][j]+=a.mat[i][k]*b.mat[k][j];//模拟矩阵乘法,算法复杂度为n的立方。
}
}
return ans;//这里返回了一个结构体,内含乘后的矩阵。
}
matrix quickpower(int x,matrix tar)//矩阵快速幂
{
matrix res;
res.n=tar.n;
res.m=tar.m;//把当前矩阵设定为等行列的单位矩阵
reset(res.mat,0);
for(int i=1; i<=res.n; i++)
for(int j=1; j<=res.m; j++)
{
if(i==j)
res.mat[i][j]=1;
else
res.mat[i][j]=0;
}
while(x)//常规快速幂
{
if(x&1)
res=multipy(res,tar);//重载运算符后为res*tar
if(!(x&1))
tar=multipy(tar,tar);//重载运算符后为tar*tar
x>>=1;
}
return res;
}
int DETERMINATION()
{
cin>>ma.n>>ma.m;
for(int i=1; i<=ma.n; i++)
for(int j=1; j<=ma.m; j++)
cin>>ma.mat[i][j];
mc=quickpower(2,ma);
for(int i=1; i<=mc.n; i++)
{
for(int j=1; j<=mc.m; j++)
cout<<mc.mat[i][j]<<" ";//输出答案矩阵
cout<<endl;
}
return 0;
}