矩阵快速幂

矩阵快速幂

1.矩阵乘法:

对于n*k的矩阵A,k*m的矩阵B,相乘的得到的矩阵C为:

 我们可以发现,对于矩阵A,B,只有当A的列等于B的行时,两个矩阵才能相乘

 Code:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50;
 4 int a[N][N],b[N][N],c[N][N];
 5 int n,k,m;
 6 int main(){
 7     cin>>n>>k>>m;
 8     for(int i=1;i<=n;i++){
 9         for(int j=1;j<=k;j++){
10             cin>>a[i][j];
11         }
12     }
13     for(int i=1;i<=k;i++){
14         for(int j=1;j<=m;j++){
15             cin>>b[i][j];
16         }
17     }
18     for(int i=1;i<=n;i++){
19         for(int j=1;j<=m;j++){
20             for(int r=1;r<=k;r++){
21                 c[i][j]+=a[i][r]*b[r][j];
22             }
23         }
24     }
25     for(int i=1;i<=n;i++){
26         for(int j=1;j<=m;j++){
27             cout<<c[i][j]<<" ";
28         }
29         cout<<endl;
30     }
31 } 

 

2.矩阵快速幂

在学习矩阵乘法后,我们便可以开始学习矩阵快速幂了。

老规矩,直接上例题:

计算斐波那契数列第n项的后四位(n<=1e9)。

好家伙,这不递推板题嘛!~

仔细点,n<=1e9!

对于如此之大的数据规模,我们只能用O(logn)或O(√n)的算法来实现。

那O(logn)的快速幂算法就十分合适了。

我们先列出递推方程式:

其中,1 1 1 0这个矩阵可以通过方程求得。

 

 

 于是,我们只需要类比普通的快速幂计算1 1 1 0这个矩阵即可。

 附上矩阵快速幂的模板:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 const int N=110;
 5 const int P=1e9+7;
 6 int k,n;
 7 int ans[N][N],x[N][N],dx[N][N];
 8 
 9 void pow1(){
10     for(int i=1;i<=n;i++){
11         for(int j=1;j<=n;j++){
12             dx[i][j]=ans[i][j];
13             ans[i][j]=0;
14         }
15     }
16     for(int i=1;i<=n;i++){
17         for(int j=1;j<=n;j++){
18             for(int k=1;k<=n;k++){
19                 ans[i][j]=(ans[i][j]+dx[i][k]*x[k][j]%P)%P;
20             }
21         }
22     }
23 }
24 
25 void pow2(){
26     for(int i=1;i<=n;i++){
27         for(int j=1;j<=n;j++){
28             dx[i][j]=x[i][j];
29             x[i][j]=0;
30         }
31     }
32     for(int i=1;i<=n;i++){
33         for(int j=1;j<=n;j++){
34             for(int k=1;k<=n;k++){
35                 x[i][j]=(x[i][j]+dx[i][k]*dx[k][j]%P)%P;
36             }
37         }
38     }
39 }
40 
41 signed main(){
42     cin>>n>>k;
43     for(int i=1;i<=n;i++){
44         for(int j=1;j<=n;j++){
45             cin>>ans[i][j];
46             x[i][j]=ans[i][j];
47         }
48     }
49     k--;
50     while(k){
51         if(k%2==1) pow1();
52         pow2();
53         k/=2;
54     }
55     for(int i=1;i<=n;i++){
56         for(int j=1;j<=n;j++){
57             cout<<ans[i][j]<<" ";
58         }
59         cout<<endl;
60     } 
61     return 0;
62 }

 

posted @ 2021-07-15 19:12  爆零王  阅读(394)  评论(0)    收藏  举报