[原博客存档] [模板] 矩阵快速幂
Luogu P3390 [模板]矩阵快速幂
题目背景
矩阵快速幂
题目描述
给定n*n的矩阵A,求A^k
输入输出格式
输入格式:
第一行,n,k第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素
输出格式:
输出A^k共n行,每行n个数,第i行第j个数表示矩阵第i行第j列的元素,每个元素模10^9+7
输入输出样例
输入样例#1:
2 1 1 1 1 1输出样例#1:
1 1 1 1说明
n<=100, k<=10^12, |矩阵元素|<=1000 算法:矩阵快速幂
Solution:
给定一个n*m的矩阵A和m*k的矩阵B,A×B得到一个n*k的矩阵C。
怎么理解呢?矩阵C的某行某列就是A的某行乘以B的某列。
某行乘以某列就是行上的元素分别与列上的元素按顺序相乘最后相加的结果。
所以对于矩阵C,m根本不重要,n和k决定矩阵C的大小。
那么矩阵A和矩阵B为什么一定要求m相等呢?
原因是如果m不等的话某行某列相乘就会有某些元素不够乘。
什么是单位矩阵呢?使得任意矩阵A有S*A=A的矩阵S就叫单位矩阵。相当于乘法里的1。
单位矩阵的行数列数相等。
单位矩阵的构造就是左上开始向右下的45度斜线上的元素是1,其余是0。
我们使用结构体加上运算符重载来实现这一操作。
Codes:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MOD=1e9+7; 4 typedef long long ll; 5 6 int n; 7 struct matrix{ 8 static const short N=110; 9 int a[N][N]; 10 matrix(bool init=false){ 11 memset(a,0,sizeof(a)); 12 if(init){ 13 for(register int i=0;i<n;i++) 14 a[i][i]=1; 15 } // 初始化单位矩阵 16 } 17 int* operator[](int x){return a[x];} 18 matrix operator *(matrix &b){ // 不能用const(重点) 19 matrix c; 20 for(register int i=0;i<n;i++) // 枚举行 21 for(register int j=0;j<n;j++) // 枚举行与列的元素 22 for(register int k=0;k<n;k++) // 枚举列 23 c[i][k]=(c[i][k]+(1ll*a[i][j]*b[j][k])%MOD)%MOD; 24 return c; 25 } 26 }; 27 28 int main(){ 29 ll k; 30 scanf("%d%lld",&n,&k); 31 matrix x,ans(true); 32 for(int i=0;i<n;i++) 33 for(int j=0;j<n;j++) 34 scanf("%d",&x[i][j]); 35 while(k){ 36 if(k&1ll)ans=ans*x; 37 x=x*x; 38 k>>=1ll; 39 } 40 for(int i=0;i<n;i++){ 41 for(int j=0;j<n;j++){ 42 if(j)putchar(' '); 43 printf("%d",ans[i][j]); 44 } 45 putchar('\n'); 46 } 47 return 0; 48 }