版权声明:转载请保留原地址 https://blog.csdn.net/u012972031/article/details/82726275
缘起:在学这个之前学了好一阵子矩阵,仍然不太懂。。后来发现解斐波那契数列好像只需要方形矩阵就行了,就学了一下方形矩阵的乘法。
先上代码吧
#include<cstdio>
#include<iostream>
#define ll long long
#define mod 1000000007
using namespace std;
struct Mat{
ll m[101][101];
};
Mat initMat(int n);
Mat Mul(Mat a,Mat b,int n);
Mat poww(Mat a,ll b);
Mat a,e;//a:输入 e:单位矩阵
int n;//矩阵长度 (每行n个数 )
int main(){
Mat a;
int k;//k是Mat的指数
cin>>n>>k;//input 矩阵长度以及指数
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>a.m[i][j];
}
}
//初始化e
for(int i=0;i<n;i++){
e.m[i][i]=1;
}
Mat c=poww(a,k);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<c.m[i][j]%mod<<" ";
}
cout<<endl;
}
return 0;
}
Mat poww(Mat a,ll b){
Mat ans=e,base=a;
while(b!=0){
if(b&1){//如果是奇数
ans=Mul(ans,a,n);//DEBUG重点 原: Mul(ans,ans,n)
}
base=Mul(base,base,n);
b=b/2;
}
return ans;
}
Mat Mul(Mat a,Mat b,int n){//相乘
//方形矩阵 n:矩阵长或宽
Mat c=initMat(n);
for(int i=0;i<n;i++){//乘到的行数
for(int x=0;x<n;x++){//x坐标
for(int y=0;y<n;y++){//y坐标
c.m[i][x]=c.m[i][x]%mod+a.m[i][y]*b.m[y][x]%mod;
//c.m[i][x]=c.m[i][x]%mod+a.m[x][i]*b.m[x][y]%mod;
}
}
}
return c;
}
Mat initMat(int n){//初始化矩阵 n:方形矩阵长或宽
Mat c;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c.m[i][j]=0;
}
}
return c;
}
代码有点长,不过实际上就是基本矩阵+快速幂,等于在快速幂的计算过程中使用矩阵。
不过这样的话,是通不过洛谷的题目的。
题目链接:https://www.luogu.org/problemnew/show/P3390
zxc大佬的指点
1.n,k应为long long类型
2.快速幂的过程中应为 ans=Mul(ans,a,n);
AC代码如下:
#include<cstdio>
#include<iostream>
#define ll long long
#define mod 1000000007
using namespace std;
struct Mat{
ll m[101][101];
};
Mat initMat(int n);
Mat Mul(Mat a,Mat b,int n);
Mat poww(Mat a,ll b);
Mat a,e;//a:输入 e:单位矩阵
ll n;//矩阵长度 (每行n个数 )
int main(){
Mat a;
ll k;//k是Mat的指数
cin>>n>>k;//input 矩阵长度以及指数
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>a.m[i][j];
}
}
//初始化e
for(int i=0;i<n;i++){
e.m[i][i]=1;
}
Mat c=poww(a,k);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<c.m[i][j]%mod<<" ";
}
cout<<endl;
}
return 0;
}
Mat poww(Mat a,ll b){
Mat ans=e,base=a;
while(b!=0){
if(b&1){//如果是奇数
ans=Mul(ans,base,n);//DEBUG重点 原: Mul(ans,ans,n)
}
base=Mul(base,base,n);
b=b/2;
}
return ans;
}
Mat Mul(Mat a,Mat b,int n){//相乘
//方形矩阵 n:矩阵长或宽
Mat c=initMat(n);
for(int i=0;i<n;i++){//乘到的行数
for(int x=0;x<n;x++){//x坐标
for(int y=0;y<n;y++){//y坐标
c.m[i][x]=c.m[i][x]%mod+a.m[i][y]*b.m[y][x]%mod;
//c.m[i][x]=c.m[i][x]%mod+a.m[x][i]*b.m[x][y]%mod;
}
}
}
return c;
}
Mat initMat(int n){//初始化矩阵 n:方形矩阵长或宽
Mat c;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c.m[i][j]=0;
}
}
return c;
}
总结:
1.应该仔细看好题目的范围要求
2.快速幂的 ans=Mul(ans,base,n); 应当理解透彻