矩阵操作

24 篇文章 0 订阅
12 篇文章 0 订阅

矩阵操作

信息竞赛中矩阵的应用看似没用不过在实际应用中却能发挥很大的作用(可以把一些一维递推优化到log(n),还可以求路径方案等),在这里把矩阵的各种操作进行一下总结。
大体上说,矩阵操作有5种

  • 矩阵乘数
  • 矩阵的幂
  • 矩阵加法
  • 矩阵叉乘
  • 矩阵点乘

矩阵乘法具体怎么做应该都清楚,在这里也说不太清楚
上两个小图:

基本性质

1.结合性 (AB)C=A(BC).
2.对加法的分配性 (A+B)C=AC+BC,C(A+B)=CA+CB .
3.对数乘的结合性 k(AB)=(kA)B =A(kB).
4.关于转置 (AB)’=B’A’.

几种操作:

1.矩阵乘数:
n*m 的矩阵,每一位都乘 t 即使新的矩阵
2.矩阵的幂
用“快速幂”的思想,只是把x^y中的x换成矩阵而已,最好用一个结构体表示,这样结构会比较清晰。
如:最基本的用矩阵快速幂加速递推求斐波那契数列。
3.矩阵加法
前提是必须为两个大小相同的矩阵,对应位数相加得到新的矩阵
4.矩阵叉乘
正常的矩阵乘法
注: n * m 与 p * q 则 m==p
5.矩阵点乘
矩阵点乘与加法类似,同样要求必须大小相同,对应相乘即可。

一道小题:

Description:

作业中矩阵的操作有5种:

*矩阵乘数

^矩阵的幂

+矩阵加法

X矩阵叉乘

.矩阵点乘

现需要你输出对应操作后的结果

Input

第一行为两个整数,矩阵A的行n 和 列m。

第2~n+1行 每行有m个整数,整数与整数间用空格间隔,对应着矩阵A的n*m个元素。

第n+2行 一个操作符,(* ^ + X .)分别代表矩阵乘整数、矩阵幂运算、矩阵加法、矩阵叉乘、矩阵点乘

如果操作符是* 第n+3行为一个整数λ,计算λA

如果操作符是^第n+3行为一个整数e,计算Ae

如果是(+、X、.)则从第n+3行开始,是矩阵B的数据,同矩阵A的数据格式,计算A+B、AXB、A.B

Output

结果按矩阵的行列输出矩阵

Sample Input

2 2
1 1
2 0
X
2 3
0 2 3
1 1 2

Sample Output

1 3 5
0 4 6

HINT

数据保证合法
答案和所有运算的中间过程,保证不爆int


Code:

#include<stdio.h>
#include<string.h>
struct matrix
{
    int a[100][100];
}v,ans,origin;
int n,m;
int is[100][100];
void init()
{
    memset(ans.a,0,sizeof(ans.a));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(i==j)
                ans.a[i][j]=1;
            else ans.a[i][j]=0;
        }
    }
}
matrix mul(matrix x,matrix y)
{
    matrix tmp;
    memset(tmp.a,0,sizeof(tmp.a));
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            for(int k=0;k<n;k++)
            {
                tmp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
            }
        }
    }
    return tmp;
}
void cal(int n)
{
    while(n)
    {
        if(n&1)
        {
            ans=mul(ans,origin);
        }
        n>>=1;
        origin=mul(origin,origin);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            scanf("%d",&ans.a[i][j]);
        }
    }
    char s[3];
    scanf("%s",s);
    if(s[0]=='*')
    {
        int t;
        scanf("%d",&t);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(j==m-1)
                {
                    printf("%d",ans.a[i][j]*t);
                }
                else
                    printf("%d ",ans.a[i][j]*t);
            }
            printf("\n");
        }
    }
    if(s[0]=='^')
    {
        int t;
        scanf("%d",&t);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                origin.a[i][j]=ans.a[i][j];
            }
        }
        init();
        cal(t);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(j==m-1)
                {
                    printf("%d",ans.a[i][j]);
                }
                else
                    printf("%d ",ans.a[i][j]);
            }
            printf("\n");
        }
    }
    if(s[0]=='+')
    {
        int p,q;
        scanf("%d%d",&p,&q);
        for(int i=0;i<p;i++)
        {
            for(int j=0;j<q;j++)
            {
                scanf("%d",&is[i][j]);
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(j==m-1)
                {
                    printf("%d",ans.a[i][j]+is[i][j]);
                }
                else
                    printf("%d ",ans.a[i][j]+is[i][j]);
            }
            printf("\n");
        }
    }
    if(s[0]=='X')
    {
        int p,q;
        scanf("%d%d",&p,&q);
        for(int i=0;i<p;i++)
        {
            for(int j=0;j<q;j++)
            {
                scanf("%d",&v.a[i][j]);
            }
        }
        matrix tmp;
        memset(tmp.a,0,sizeof(tmp.a));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<q;j++)
            {
                for(int k=0;k<m;k++)
                {
                    tmp.a[i][j]+=(ans.a[i][k]*v.a[k][j]);
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<q;j++)
            {
                if(j==q-1)
                {
                    printf("%d",tmp.a[i][j]);
                }
                else
                    printf("%d ",tmp.a[i][j]);
            }
            printf("\n");
        }
    }
    if(s[0]=='.')
    {
        int p,q;
        scanf("%d%d",&p,&q);
        for(int i=0;i<p;i++)
        {
            for(int j=0;j<q;j++)
            {
                scanf("%d",&is[i][j]);
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(j==m-1)
                {
                    printf("%d",ans.a[i][j]*is[i][j]);
                }
                else
                    printf("%d ",ans.a[i][j]*is[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

矩阵乘法的时间复杂度是O(n^3),但可以用分治的方法进行优化。
如,A^n

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值