码迷,mamicode.com
首页 > 其他好文 > 详细

矩阵快速幂

时间:2016-03-19 01:03:56      阅读:361      评论:0      收藏:0      [点我收藏+]

标签:

参照:http://www.cnblogs.com/yan-boy/archive/2012/11/29/2795294.html

对A^n,我们一般通过连乘(n-1)次,但是我们利用矩阵乘法的结合律做一下简单的改进就能减少连乘的次数,例如,A*A*A*A*A*A  =>  (A*A)*(A*A)*(A*A),可使得连乘次数由5次减少为3次,那么究竟如何利用结合律可以得到最小的连乘次数呢?

答案是:二进制和二分思想的结合

例如,A^21  =>  (A^16)*(A^4)*(A^1)(21=2^4+2^2+2^0),A^16又可以二分为(A^8)*(A^8),A^8=(A^4)*(A^4)....

从而可将因子数由n降到log(n)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define N 100
#define ll long long 
struct Mat{
    ll mat[N][N];
};
void showmat(Mat a)
{
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
            printf("%lld ",a.mat[i][j]);
        printf("\n");
    }
}
void Init(Mat &b)//初始化为单位矩阵 ,要引用 
{
    int i, j, k;
    for(i = 0; i < 3; ++i) {
        for(j = 0; j < 3; ++j) 
        {
            b.mat[i][j] = (i == j);//简略的写法 
        }
    }
}
Mat MatMul(Mat a,Mat b)
{
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    int i, j, k;
    for(i = 0; i < 3; ++i) {
        for(j = 0; j < 3; ++j) 
        {
            for(k = 0; k < 3; ++k) 
            {
                c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
            }
        }
    }
    return c;
}
Mat MATLAB(Mat a,int n)//核心代码,例A^156=(A^4)*(A^8)*(A^16)*(A^128) 
{
    Mat b;
    Init(b);
    while(n)
    {
        if(n&1)
            b = MatMul(b,a);
        n >>= 1;//右移
        a = MatMul(a,a); 
    }
    return b;
}
int main()
{
    int n;
    Mat a,b;
    scanf("%d",&n);
    memset(a.mat,0,sizeof(a.mat));
    memset(b.mat,0,sizeof(b.mat));
    //生成三维随机矩阵 
    srand(time(0));//随机种子---stdlib.h 
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            a.mat[i][j] = rand()%100;
    printf("随机矩阵为:\n");
    showmat(a);
    b = MATLAB(a,n);
    printf("%d次幂所得结果矩阵为:\n",n);
    showmat(b);
    return 0;
}

技术分享

矩阵快速幂

标签:

原文地址:http://www.cnblogs.com/520xiuge/p/5294132.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!