矩阵乘法

Posted mowanying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵乘法相关的知识,希望对你有一定的参考价值。

概念:

A是n*m的矩阵,B是m*p的矩阵,则A*B是n*p的矩阵。

这个矩阵的某一位置的值(i,j)是A中第 i 行的每一个数 * B中第 j 行的每一个数求和的值。

比如:(图片来源

技术图片

用途:

用于处理一维递推,递推次数很大的时候:构造一个转移矩阵,根据转移方程填充转移矩阵的值。然后根据结合律,可以做矩阵快速幂来加速。

模板:P1939 【模板】矩阵加速(数列)

技术图片
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
void mul(int f[3],int a[3][3])//两两乘法 

    int tmp[3];
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<=2;i++)
     for(int k=0;k<=2;k++)
      tmp[i]=(tmp[i] + (ll) f[k]*a[k][i] %mod) %mod;//注意这里的下标 
    memcpy(f,tmp,sizeof(tmp));

void mulself(int a[3][3])//自己乘自己 

    int tmp[3][3];
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<=2;i++)
     for(int j=0;j<=2;j++)
      for(int k=0;k<=2;k++)
       tmp[i][j]=(tmp[i][j] + (ll)a[i][k]*a[k][j]%mod ) %mod;
    memcpy(a,tmp,sizeof(tmp));

int main()

    int T,n;
    scanf("%d",&T);
    while(T--)
        scanf("%d",&n);
        int f[3]=1,1,1;//初始状态数组 
        int a[3][3]=0,0,1,1,0,0,0,1,1;//转移数组 
        n--;//根据题意适当地-- 
        while(n)
            if(n&1) mul(f,a);
            mulself(a);
            n>>=1;
         
        printf("%d\\n",f[0]);
    
 
/*
3
6
8
10
*/
模板

P1962 斐波那契数列

技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
void mul(int f[2],int a[2][2])

    int tmp[2];
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<=1;i++)
     for(int k=0;k<=1;k++)
         tmp[i]=( tmp[i]+(ll)f[k]*a[k][i] %mod ) %mod;//!!!k 这里是k 因为是行*列 
     
    memcpy(f,tmp,sizeof(tmp));

void mulself(int a[2][2])

    int tmp[2][2];
    memset(tmp,0,sizeof(tmp));//!!!一定要记得清零啊!!否则会是一些莫名其妙的值 
    for(int i=0;i<=1;i++)//注意下标是从0开始 
     for(int j=0;j<=1;j++)
      for(int k=0;k<=1;k++)
          tmp[i][j]=( tmp[i][j]+(ll)a[i][k]*a[k][j] %mod ) %mod;
      
    memcpy(a,tmp,sizeof(tmp));

int main()

    ll n;
    scanf("%lld",&n);
    int f[2]=0,1;
    int c[2][2]=0,1,1,1;
    while(n)
        if(n&1) mul(f,c);
        mulself(c);
        n>>=1;
    
    printf("%d\\n",f[0]);
斐波拉契

 

P4838 P哥破解密码

技术图片
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 19260817
void mul(int f[3],int a[3][3])

    int tmp[3];
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<=2;i++)
     for(int k=0;k<=2;k++)
         tmp[i]=(tmp[i] + (ll)f[k]*a[k][i] %mod) %mod;
     
    memcpy(f,tmp,sizeof(tmp));

void mulself(int a[3][3])

    int tmp[3][3];
    memset(tmp,0,sizeof(tmp));
    for(int i=0;i<=2;i++)
     for(int j=0;j<=2;j++)
         for(int k=0;k<=2;k++)
         tmp[i][j]=(tmp[i][j] + (ll)a[i][k]*a[k][j] %mod) %mod;
     
    
    memcpy(a,tmp,sizeof(tmp));

int main()

    int T,n;
    scanf("%d",&T);
    while(T--)
        scanf("%d",&n);
        int f[3]=1,1,0;
        int a[3][3]=1,1,0,1,0,1,1,0,0;
        n--;
        while(n)
            if(n&1) mul(f,a);
            mulself(a);
            n>>=1;
        
        printf("%d\\n",( (f[0]+f[1]) %mod + f[2] ) %mod  );//这个+mod写在外面啊!!!仔细一点检查!!! 
    

/*
3
1
3
6
*/
P哥破解密码

注意:

1.记得清零

2.下标看清楚

3.mod不要写错位置

 

以上是关于矩阵乘法的主要内容,如果未能解决你的问题,请参考以下文章

矩阵的乘法运算怎么算?

CUDA做矩阵乘法如何计算所需显存

矩阵的乘法运算法则

矩阵的乘法运算

矩阵乘法 codevs 1287 矩阵乘法

Spark中的矩阵乘法分析