zoukankan      html  css  js  c++  java
  • 矩阵乘法以及矩阵快速幂模板

    两矩阵 A * B ,当 A 的行数等于 B 的列数时,A * B 合法,结果如下:

     1 #include<stdio.h>
     2 #include<string.h>
     3 typedef long long ll;
     4 const int mod=10000007;
     5 
     6 struct mat{
     7     int r,c;          //r即row,矩阵行数;c即column,矩阵列数
     8     ll m[10][10];    //矩阵
     9     void clear(){    //归零函数
    10     for(int i=1;i<=r;i++)memset(m[i],0,sizeof(m[i]));
    11     }
    12 };
    13 
    14 mat MatMul(mat m1,mat m2){    //仅当m1.r==m2.c时可以相乘,相乘时可加模运算
    15     mat tmp;
    16     tmp.r=m1.r;        //计算结果的行数与m1行数相等,列数与m2列数相等
    17     tmp.c=m2.c;
    18     int i,j,k;
    19     for(i=1;i<=tmp.r;i++){
    20         for(j=1;j<=tmp.c;j++){
    21             ll t=0;
    22             for(k=1;k<=m1.c;k++){
    23                 t=(t+(m1.m[i][k]*m2.m[k][j])%mod)%mod;
    24             }
    25             tmp.m[i][j]=t;
    26         }
    27     }
    28     return tmp;
    29 }
    30 
    31 int main(){
    32     int t;
    33     while(scanf("%d",&t)!=EOF){
    34         mat m[2];
    35         for(int i=0;i<=1;i++){
    36             scanf("%d%d",&m[i].r,&m[i].c);
    37             for(int j=1;j<=m[i].r;j++){
    38                 for(int k=1;k<=m[i].c;k++){
    39                     scanf("%lld",&m[i].m[j][k]);
    40                 }
    41             }
    42         }
    43         mat ans=MatMul(m[0],m[1]);
    44         for(int i=1;i<=ans.r;i++){
    45             for(int j=1;j<=ans.r;j++){
    46                 printf("%lld ",ans.m[i][j]);
    47             }
    48             printf("
    ");
    49         }
    50     }
    51     return 0;
    52 }

    在之前的矩阵乘法的基础上,引入快速幂的思想,就得到了矩阵的快速幂算法(MatQP,计算矩阵 a 的 n 次幂):

    经过修改,把矩阵加法、乘法、快速幂全部重载了一下,写了构造函数,其中矩阵快速幂支持0次幂等于单位矩阵:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 typedef long long ll;
     5 int mod;
     6 
     7 struct mat{
     8     int r,c;
     9     ll m[4][4];        //经测试最大开成590*590的 ll 型矩阵
    10     mat(){}
    11     mat(int r,int c):r(r),c(c){}
    12     void clear(){
    13         memset(m,0,sizeof(m));
    14     }
    15 
    16     mat operator+(mat a)const{
    17         mat ans(r,c);
    18         for(int i=1;i<=r;i++){
    19             for(int j=1;j<=c;j++){
    20                 ans.m[i][j]=(m[i][j]+a.m[i][j])%mod;
    21             }
    22         }
    23         return ans;
    24     }
    25 
    26     mat operator*(mat a)const{
    27         mat tmp(r,a.c);
    28         int i,j,k;
    29         for(i=1;i<=tmp.r;i++){
    30             for(j=1;j<=tmp.c;j++){
    31                 tmp.m[i][j]=0;
    32                 for(k=1;k<=c;k++){
    33                     tmp.m[i][j]=(tmp.m[i][j]+(m[i][k]*a.m[k][j])%mod)%mod;
    34                 }
    35             }
    36         }
    37         return tmp;
    38     }
    39 
    40     mat operator^(int n)const{        //需要时可以用 ll n,注意运算符优先级比较低,多用括号;
    41         mat ans(r,r),tmp(r,r);
    42         memcpy(tmp.m,m,sizeof(tmp.m));
    43         ans.clear();
    44         for(int i=1;i<=ans.r;i++){
    45             ans.m[i][i]=1;
    46         }
    47         while(n){
    48             if(n&1)ans=ans*tmp;
    49             n>>=1;
    50             tmp=tmp*tmp;
    51         }
    52         return ans;
    53     }
    54     
    55     void print()const{
    56         for(int i=1;i<=r;i++){
    57             for(int j=1;j<=c;j++){
    58                 printf("%lld",m[i][j]);
    59                 if(j==c)printf("
    ");
    60                 else printf(" ");
    61             }
    62         }
    63     }
    64 
    65 };

     

    非结构体封装版:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 typedef long long ll;
     5 const int mod=1e9+7;
     6 
     7 struct mat{
     8     int r,c;
     9     ll m[4][4];
    10     mat(){}
    11     mat(int r,int c):r(r),c(c){}
    12 };
    13 
    14 void clear(mat &a){
    15     memset(a.m,0,sizeof(a.m));
    16 }
    17 
    18 mat mul(mat a,mat b){
    19     mat tmp(a.r,b.c);
    20     int i,j,k;
    21     for(i=1;i<=tmp.r;i++){
    22         for(j=1;j<=tmp.c;j++){
    23             tmp.m[i][j]=0;
    24             for(k=1;k<=a.c;k++){
    25                 tmp.m[i][j]=(tmp.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
    26             }
    27         }
    28     }
    29     return tmp;
    30 }
    31 
    32 mat QP(mat a,int n){
    33     mat ans(a.r,a.r),tmp(a.r,a.r);
    34     memcpy(tmp.m,a.m,sizeof(tmp.m));
    35     clear(ans);
    36     for(int i=1;i<=ans.r;i++){
    37         ans.m[i][i]=1;
    38     }
    39     while(n){
    40         if(n&1)ans=mul(ans,tmp);
    41         n>>=1;
    42         tmp=mul(tmp,tmp);
    43     }
    44     return ans;
    45 }
    46 
    47 void print(mat a){
    48     for(int i=1;i<=a.r;++i){
    49         for(int j=1;j<=a.c;++j){
    50             printf("%lld",a.m[i][j]);
    51             if(j==a.c)printf("
    ");
    52             else printf(" ");
    53         }
    54     }
    55 }
    56 
    57 int main(){
    58 
    59     return 0;
    60 }

    另外,遇到题目需要将矩阵运算的乘法和加法分别改为加法和min/max,只要满足矩阵运算结合律,都是可以改写的,此处循环遍历的下标从 0 开始

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll INF = 0x3f3f3f3f3f3f3f3f;
     5 
     6 struct mat{
     7     int r,c;
     8     ll m[45][45];
     9     mat(){}
    10     mat(int r,int c):r(r),c(c){}
    11 };
    12 
    13 void clear(mat &a){
    14     memset(a.m,0x3f,sizeof(a.m));
    15 }
    16 
    17 inline ll min(ll a, ll b){return a <= b ? a : b ;}
    18 
    19 mat mul(mat a,mat b){
    20     mat tmp(a.r,b.c);
    21     clear(tmp);
    22     int i,j,k;
    23     for(i=0;i<tmp.r;i++){
    24         for(j=0;j<tmp.c;j++){
    25             for(k=0;k<a.c;k++){
    26                 tmp.m[i][j]=min(tmp.m[i][j], a.m[i][k] + b.m[k][j]);
    27             }
    28         }
    29     }
    30     return tmp;
    31 }
    32 
    33 mat QP(mat a,int n){
    34     mat ans(a.r,a.r),tmp(a.r,a.r);
    35     memcpy(tmp.m,a.m,sizeof(tmp.m));
    36     clear(ans);
    37     for(int i=0;i<ans.r;i++){
    38         ans.m[i][i]=0;
    39     }
    40     while(n){
    41         if(n&1)ans=mul(ans,tmp);
    42         n>>=1;
    43         tmp=mul(tmp,tmp);
    44     }
    45     return ans;
    46 }
    47 
    48 void print(mat a){
    49     for(int i=0;i<a.r;++i){
    50         for(int j=0;j<a.c;++j){
    51             printf("%lld",a.m[i][j]);
    52             if(j==a.c-1)printf("
    ");
    53             else printf(" ");
    54         }
    55     }
    56 }

  • 相关阅读:
    Grid search in the tidyverse
    Handling Class Imbalance with R and Caret
    R语言-Kindle特价书爬榜示例 & 输出HTML小技巧(转)
    Centos7下安装部署MXNET
    特征选择, 经典三刀(转)
    vue知识点14
    vue知识点13
    vue知识点12
    vue知识点11
    vue知识点10
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4443176.html
Copyright © 2011-2022 走看看