矩阵乘法和快速幂的一些优化和剪枝

矩阵相乘

一般会用O(n^3)的方法。。。配合剪枝【添条件,设门槛。。。】

//O(n^3)算法  
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <cstdlib>  
#include <cmath>  
#include <algorithm>  
using namespace std;  
#define LL __int64  
#define MOD 1000  
typedef struct MATRIX  
{  
    int mat[50][50];  
}MATRIX;  
  
MATRIX mat_multiply (MATRIX a,MATRIX b,int n)  
{  
    MATRIX c;   //c[i][j]= Σ a[i][k]*b[k][j]  
    memset(c.mat,0,sizeof(c.mat));      
/* 
    for(int i=0;i<n;i++)    //a矩阵一行一行往下 
        for(int j=0;j<n;j++)    //b矩阵一列一列往右 
            for(int k=0;k<n;k++)    //使a矩阵 第i行第k个元素 乘以 b矩阵 第j列第k个元素 
                if(a[i][k] && b[k][j])    //剪枝(添条件,设门槛),提高效率,有一个是0,相乘肯定是0 
                    c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; 
*/  
  
//上面也是可以的,但是下面的剪枝更好一些,效率更高一些,但是运算顺序有点难想通,,,  
//上面就是C[i][j]一次就求出来,下面就是每次c[i][j]求出一项【就是上面红体字,每次各求一列】  
  
    for(int k=0;k<n;k++)    //这个可以写到前面来,  
        for(int i=0;i<n;i++)  
            if(a.mat[i][k])     //剪枝:如果a.mat[i][k]是0,就不执行了  
                for(int j=0;j<n;j++)  
                    if(b.mat[k][j])     //剪枝:如果b.mat[i][k]是0,就不执行了  
                    {  
                        c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];  
                        if(c.mat[i][j]>=MOD)    //这个看实际需求,要不要取模  
                            c.mat[i][j]%=MOD;   //取模的复杂度比较高,所以尽量减少去模运算,添加条件,只有当大于等于MOD的时候才取余  
                    }  
    return c;  
}  
  
int main()<span style="white-space:pre">  </span>//这个只是用来测试用的。。。  
{  
    int n;  
    MATRIX A,B,C;  
  
    memset(A.mat,0,sizeof(A.mat));  
    memset(B.mat,0,sizeof(B.mat));  
    memset(C.mat,0,sizeof(C.mat));  
  
    scanf("%d",&n);     //矩阵规模,这里是方阵,行数等于列数  
  
    for(int i=0;i<n;i++)    //初始化A矩阵  
        for(int j=0;j<n;j++)  
            scanf("%d",&A.mat[i][j]);  
  
    for(int i=0;i<n;i++)    //初始化B矩阵  
        for(int j=0;j<n;j++)  
            scanf("%d",&B.mat[i][j]);  
  
    C=mat_multiply (A,B,n);  
  
    for(int i=0;i<n;i++)    //打印C矩阵  
    {  
        for(int j=0;j<n;j++)  
            printf("%3d",C.mat[i][j]);  
        printf("\n");  
    }  
    return 0;  
}

矩阵快速幂

//矩阵快速幂  
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <cstdlib>  
#include <cmath>  
#include <algorithm>  
using namespace std;  
#define LL __int64  
#define MOD 1000  
typedef struct MATRIX  
{  
    int mat[50][50];  
}MATRIX;  
  
MATRIX mat_multiply (MATRIX a,MATRIX b,int n)  
{  
    MATRIX c;   //c[i][j]= Σ a[i][k]*b[k][j]  
    memset(c.mat,0,sizeof(c.mat));  
/* 
    for(int i=0;i<n;i++)    //a矩阵一行一行往下 
        for(int j=0;j<n;j++)    //b矩阵一列一列往右 
            for(int k=0;k<n;k++)    //使a矩阵 第i行第k个元素 乘以 b矩阵 第j列第k个元素 
                if(a[i][k] && b[k][j])    //剪枝(添条件,设门槛),提高效率,有一个是0,相乘肯定是0 
                    c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; 
*/  
  
//上面也是可以的,但是下面的剪枝更好一些,效率更高一些,但是运算顺序有点难想通,,,  
//上面就是C[i][j]一次就求出来,下面就是每次c[i][j]求出一项【就是上面红体字,每次各求一列】  
  
    for(int k=0;k<n;k++)    //这个可以写到前面来,  
        for(int i=0;i<n;i++)  
            if(a.mat[i][k])     //剪枝:如果a.mat[i][k]是0,就不执行了  
                for(int j=0;j<n;j++)  
                    if(b.mat[k][j])     //剪枝:如果b.mat[i][k]是0,就不执行了  
                    {  
                        c.mat[i][j]+=a.mat[i][k]*b.mat[k][j];  
                        if(c.mat[i][j]>=MOD)    //这个看实际需求,要不要取模  
                            c.mat[i][j]%=MOD;   //取模的复杂度比较高,所以尽量减少去模运算,添加条件,只有当大于等于MOD的时候才取余  
                    }  
    return c;  
}  
  
MATRIX mat_quick_index(MATRIX a,int N,int n)  
{  
    MATRIX E;   //单位矩阵,就像数值快速幂里,把代表乘积的变量初始化为1  
  
//    memset(E.mat,0,sizeof(E.mat));  //置零,单位矩阵除了主对角线都是1,其他都是0  
//    for(int i=0;i<n;i++)    //初始化单位矩阵【就是主对角线全是1】  
//            E.mat[i][i]=1;  
  
    for(int i=0;i<n;i++)  
        for(int j=0;j<n;j++)  
            E.mat[i][j]=(i==j); //酷炫*炸天的初始化!!!  
  
    while(N>0)  
    {  
        if(N & 1)  
            E=mat_multiply(E,a,n);  
        N>>=1;  
        a=mat_multiply(a,a,n);  
    }  
    return E;  
}  
  
int main()  
{  
    int n,N;    //n为矩阵(方阵)规模,几行,N为指数  
    MATRIX A,C;  
  
    memset(A.mat,0,sizeof(A.mat));  
    memset(C.mat,0,sizeof(C.mat));  
  
    scanf("%d",&n);     //矩阵规模,这里是方阵,行数等于列数  
  
    for(int i=0;i<n;i++)    //初始化A矩阵  
        for(int j=0;j<n;j++)  
            scanf("%d",&A.mat[i][j]);  
  
    scanf("%d",&N);  
    C=mat_quick_index(A,N,n);  
  
    for(int i=0;i<n;i++)    //打印C矩阵  
    {  
        for(int j=0;j<n;j++)  
            printf("%3d",C.mat[i][j]);  
        printf("\n");  
    }  
    return 0;  
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值