C++ 蓝桥杯题目讲解汇总(持续更新)
VIP试题 矩阵乘法
资源限制
时间限制:1.0 s 内存限制:512.0 MB
问题描述
给定一个N阶矩阵A,输出A的M次幂(M是非负整数)
例如:
A =
1 2
3 4
A的2次幂
7 10
15 22
输入格式
第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数
接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值
输出格式
输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开
样例输入
2 2
1 2
3 4
样例输出
7 10
15 22
思路
- 矩阵快速幂,由于刚开始做入门训练斐波那契数列时候花很长时间整理了快速幂和矩阵快速幂,所以这里使用矩阵快速幂,幸运的是算法上一遍就过了,时间没白花嘎嘎
- 暴力直接循环
代码-C++
方案一:矩阵快速幂
补充:我在使用矩阵快速幂的时候,由于不熟悉C++的语法,当二维数组作为函数形参的时候遇到了很多问题,包括二维数组的列数必须声明,但是长度n的必须也要声明,这时候就出问题了,后来在朋友和百度情况下,利用指针大致地理解了一下,我会贴两份代码,一份是我第一次做的时候,由于n没法输入固定在代码(这是一个bug版的)里修改,直接输入m和矩阵就行的方案,还有一份就是标准的解题的答案,但是改动了不少,前者的思路简洁明了,但是限于语法阵亡了,同学说还可以使用vector作为参数,我尚未试试,待补充
后来在同学点醒下,用常量定义数组代替变量定义数组,毕竟我们需要用的是0-n下标的数组值,多的也不需要考虑,我们就直接开范围内最大的数组就可以解决由于变量定义数组带来的问题了
非变量定义数组代码
#include<iostream>
#include<string.h>
using namespace std;
const int N=35;
int res [N][N];
//矩阵乘法
void multi(int a[][N], int b[][N],int n){
int tmp[N][N];
memset(tmp,0,sizeof tmp);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
for (int k=0;k<n;k++)
tmp[i][j]+=a[i][k]*b[k][j];
//更新A矩阵,为下一次使用做准备
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
//矩阵快速幂 ,m代表幂
void QuickPow(int a[][N], int m,int n){
//设置结果矩阵
memset(res,0,sizeof res);
// 转换为单位矩阵
for(int i=0;i<n;i++) res[i][i] = 1;
while(m){
if(m&1) multi(res,a,n);
// 通过将幂转为二进制,加快计算
multi(a,a,n);
m>>=1;
}
}
int main(){
int n,m;
cin>>n>>m;
int lst[N][N];
// int lst [n][n] ={{1,2},{3,4}};
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
cin>>lst[i][j];
QuickPow(lst,m,n);
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
cout<<res[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
使用指针的代码
#include<iostream>
#include<cstdlib>
#include<string.h>
using namespace std;
// const int n=2;
int **res=NULL;
int **lst=NULL;
//矩阵乘法
void multi(int** a,int** b,int n){
int tmp[n][n];
memset(tmp,0,sizeof tmp);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
for (int k=0;k<n;k++)
tmp[i][j]+=a[i][k]*b[k][j];
//更新A矩阵,为下一次使用做准备
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
a[i][j]=tmp[i][j];
}
//矩阵快速幂 ,m代表幂
void QuickPow(int m, int n){
// 转换为单位矩阵
for(int i=0;i<n;i++) res[i][i] = 1;
while(m){
if(m&1) multi(res,lst,n);
// 通过将幂转为二进制,加快计算
multi(lst,lst,n);
m>>=1;
}
}
int main()
{
int m, n;
cin >>n>> m;
lst=(int**)malloc(sizeof(int*)*n);
res=(int**)malloc(sizeof(int*)*n);
for (int i = 0; i < n; ++i)
{
res[i]=(int*)malloc(sizeof(int)*n);
lst[i]=(int*)malloc(sizeof(int)*n);
for(int j=0; j < n; ++j)
res[i][j]=0;
}
// int lst [n][n] ={{1,2},{3,4}};
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
cin>>lst[i][j];
QuickPow(m,n);
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
cout<<res[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
方案二:暴力循环直接用单位矩阵乘以计算的矩阵
//矩形面积交
#include<iostream>
#include<string.h>
using namespace std;
int n,m;
int main(){
cin>>n>>m;
int lst[n][n];
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
cin>>lst[i][j];
int tmp[n][n];
memset(tmp,0,sizeof tmp);
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
tmp[i][j]=lst[i][j];
}
}
if (m==0){
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
(i==j) ? cout<<1<<" " : cout<<0<<" ";
}
cout<<endl;
}
}
else{
for (int i=1;i<m;i++){
int res[n][n];
memset(res,0,sizeof res);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
for (int k=0;k<n;k++)
res[i][j]+=lst[i][k]*tmp[k][j];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
lst[i][j]=res[i][j];
}
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
cout<<lst[i][j]<<" ";
}
cout<<endl;
}
}
return 0;
}