矩阵相关

目录

  • 矩阵前置芝士

    • 矩阵加法:
    • 矩阵减法:
    • 矩阵乘法:
  • 矩阵快速幂
  • 斐波那契数列
  • 矩阵递推相关
  • 矩阵快速幂优化DP

矩阵前置芝士

矩阵:看成一个二维数组就好了.

矩阵加法:

本人认为没用
条件:两个大小相同的矩阵
对应位置相加,形成相同大小的矩阵.

矩阵减法:

本人认为没用
条件:两个大小相同的矩阵

对应位置相减,形成相同大小的矩阵.

矩阵乘法:

这个很重要
条件:两个大小不完全一样的矩阵,必须保证矩阵\(A(n*k)\),矩阵B大小是\(k*m\)的,形成的矩阵C大小是\(n*m\)的
C矩阵中的x,y位置是A矩阵的X行,B矩阵的Y列相加.
代码:

for(int i = 1;i <= n;++ i) {
    for(int j = 1;j <= m;++ j) {
        for(int l = 1;l <= k;++ l)
            C[i][j] += A[i][k] + B[k][j];
    }
}

性质:
矩阵乘法具有结合律:
\(A*B*C = (A*B)*C = A*(B*C)\)

矩阵快速幂

ps:使用矩阵快速幂的时候一定要有模数.
根据矩阵乘法具有结合律的性质,我们可以做矩阵的快速幂:
例题---Luogu矩阵快速幂
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
const int mod = 1e9 + 7;
const int X = 110;

ll n,k;

struct Node {
    ll a[X][X];
    void clear() {
        memset(a,0,sizeof(a));
    }
}res,ans;

Node mul(Node a,Node b) {
    Node tmp;
    tmp.clear();
    for(int i = 1;i <= n;++ i) {
        for(int j = 1;j <= n;++ j) {
            for(int k = 1;k <= n;++ k) {
                tmp.a[i][j] = (tmp.a[i][j] + (a.a[i][k] * b.a[k][j]) % mod ) % mod;
            }
        }
    }
    return tmp;
}

void fast_pow(ll k) {
    for(int i = 1;i <= n;++ i)
        ans.a[i][i] = 1;
    for(;k;k >>= 1,res = mul(res,res)) {
        if(k & 1)ans = mul(ans,res);
    }
    return ;
}

int main() {
    scanf("%lld%lld",&n,&k);
    for(int i = 1;i <= n; ++i ) {
        for(int j = 1;j <= n;++ j) {
            scanf("%lld",&res.a[i][j]);
        }
    }
    ans.clear();
    fast_pow(k);
    for(int i = 1;i <= n;++ i) {
        for(int j = 1;j <= n;++ j) {
            printf("%lld ",ans.a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

/*
5
5
1 1 1 1 1
1 0 0 1 0
0 0 2 3 1
0 0 0 1 0
5 5 5 5 5
*/

斐波那契数列

我们可以通过矩阵快速幂来优化斐波那契数列斐波那契数列:\[f[n] = f[n - 1] + f[n - 2]\]
放道例题:
斐波那契数列---Luogu1962
如何做:
斐波那契数列的通项公式???
显然不行,有精度问题.
那我们来做矩阵快速幂
题目中有f[1] = 1,f[2] = 1
先构造矩阵(先不用管为什么这样构造):
\[
\left\{
\begin{matrix}
1 & 1 \ \end{matrix}
\right\} \tag{1}
\]
表示
\[
\left\{
\begin{matrix}
斐波那契数列第二项 & 斐波那契数列第一项 \ \end{matrix}
\right\} \tag{2}
\]
尝试往后推一项
我们想要矩阵成这个样子
\[
\left\{
\begin{matrix}
斐波那契数列第三项 & 斐波那契数列第二项 \ \end{matrix}
\right\} \tag{2}
\]
那我们要乘一个矩阵
首先根据矩阵的定义,我们必须要构造一个\(2*2\)的矩阵
首先给出构造好的矩阵:
\[
\left\{
\begin{matrix}
1 & 1\ 1 & 0 \ \end{matrix}
\right\} \tag{3}
\]
模拟一下就好了.
构造就是 根据生成的矩阵来构造中间的这个矩阵
我们再回过头来看一下,为什么刚开始的矩阵是
\[
\left\{
\begin{matrix}
1 & 1 \ \end{matrix}
\right\} \tag{1}
\]
因为f[3]要用到这两项啊.
记住,矩阵快速幂中间的矩阵不可改变.
这样我们就可以进行中间的矩阵\(n -2\)次幂的运算来获得一个矩阵啦,
然后用刚开始的矩阵与这个矩阵相乘就得到第n项了.
注意特判\(n == 1,n == 2\)的特殊情况

#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
const int maxN = 100 + 7;
const ll mod = 1000000007;
using namespace std;

ll n,m,k;
struct Marix{
    ll s[maxN][maxN];
    void clear() {
        memset(s,0,sizeof(s));
        return;
    }
}ans,now,a;

Marix work(Marix a,Marix b) {
    Marix c;
    c.clear();
    for(ll i = 1;i <= n;++ i)
        for(ll j = 1;j <= n;++ j)
            for(ll k = 1;k <= n;++ k)
                c.s[i][j] = ( c.s[i][j]  % mod+ ( a.s[i][k] * b.s[k][j] ) % mod ) % mod;
    return c;
}

void fast_pow() {
    ans.clear();
    for(ll i = 1;i <= n;++ i) {
        ans.s[i][i] = 1;
    }
    for(now = a;k;k >>= 1,now = work(now,now)) {
        if(k & 1) ans = work(ans,now);
    }
    Marix Q;
    Q.s[1][1] = 1;Q.s[1][2] = 1;
    ans = work(Q,ans);
    printf("%lld",ans.s[1][1]);
}

int main() {
    n = 2;
    scanf("%lld",&k);
    if(k == 1) {
        printf("1");
        return 0;
    }
    if(k == 2) {
        printf("1");
        return 0;
    }
    k -= 2;
    a.s[1][1] = 1;a.s[1][2] = 1;
    a.s[2][1] = 1;a.s[2][2] = 0;
    fast_pow();
    return 0;
}

矩阵递推相关

给道例题:Luogu1939
建议自己先构造一下:
开始矩阵:
\[
\left\{
\begin{matrix}
1 (第一项)& 1(第二项) & 1(第三项)\ \end{matrix}
\right\} \tag{1}
\]
中间的矩阵:
\[
\left\{
\begin{matrix}
0 & 0 & 1\ 1 & 0 &0 \ 0 & 1 & 1\ \end{matrix}
\right\} \tag{1}
\]

#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
const int maxN = 100 + 7;
const int mod = 1e9 + 7;
using namespace std;

ll n,m,k;
struct Marix{
    ll s[maxN][maxN];
    void clear() {
        memset(s,0,sizeof(s));
        return;
    }
}ans,now,a;

Marix work(Marix a,Marix b) {
    Marix c;
    c.clear();
    for(ll i = 1;i <= n;++ i)
        for(ll j = 1;j <= n;++ j)
            for(ll k = 1;k <= n;++ k)
                c.s[i][j] = ( c.s[i][j]  % mod+ ( a.s[i][k] * b.s[k][j] ) % mod ) % mod;
    return c;
}

void fast_pow() {
    ans.clear();
    for(ll i = 1;i <= n;++ i) {
        ans.s[i][i] = 1;
    }
    for(now = a;k;k >>= 1,now = work(now,now)) {
        if(k & 1) ans = work(ans,now);
    }
    Marix Q;
    Q.s[1][1] = 1;Q.s[1][2] = 1;Q.s[1][3] = 1;
    ans = work(Q,ans);
    printf("%lld\n",ans.s[1][3]);
}

int main() {
    n = 3;
    int T;
    scanf("%d",&T);
    while(T --) {
        a.s[1][3] = a.s[2][1] = a.s[3][2] = a.s[3][3] = 1;
        scanf("%lld",&k);
        k -= 3;
        if(k <= 0) printf("1\n");
        else fast_pow();
    }
    return 0;
}

矩阵快速幂优化DP

设置状态f[i][j][k]表示i到j走k步的方案数
设f[i][j][1] = 0/1表示i到j有没有路(0代表无路,1代表有)
枚举中间点Q
\(f[i][j][k] = \sum_{Q=1}^{n}f[i][Q][k - 1] * f[Q][j][1]\)
HDU2157

#include <iostream>
#include <cstdio>
#include <cstring>
const int maxN = 20 + 7;
const int mod = 1000;
using namespace std;

struct Matrix
{
    int s[maxN][maxN];
    Matrix() {memset(s,0,sizeof(s));}
};

int n,m;

Matrix operator * (const Matrix &a,const Matrix &b) {
    Matrix c;
    for(int i = 1;i <= n;++ i) {
        for(int j = 1;j <= n;++ j) {
            for(int k = 1;k <= n;++ k) {
                c.s[i][j] = (c.s[i][j] + a.s[i][k] * b.s[k][j] % mod) % mod;
            }
        }
    }
    return c;
}

Matrix fast_pow(Matrix a,int nn) {
    Matrix ans;
    for (int i = 1;i <= n; ++i)
        ans.s[i][i] = 1;
    for (; nn; nn >>= 1,a = a * a)
    {
        if(nn & 1) ans = ans * a;
    }
    return ans;
}

int main()
{
    while(~scanf("%d%d",&n,&m) && (n || m)) {
        Matrix q;
        for(int i = 1,u,v;i <= m;++ i) {
            scanf("%d%d",&u,&v);
            q.s[u + 1][v + 1] = 1;
        }
        int T;
        scanf("%d",&T);
        int s,t,k;
        while(T --) {
            scanf("%d%d%d",&s,&t,&k);
            Matrix b;
            b = fast_pow(q,k);
            printf("%d\n", b.s[s + 1][t + 1]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/tpgzy/p/9535017.html

时间: 2024-07-29 04:08:29

矩阵相关的相关文章

Python 矩阵相关

Python 中矩阵运算主要使用numpy库.NumPy的主要对象是同种元素的多维数组.这是一个所有的元素都是一种类型.通过一个正整数索引的元素表格(通常是元素是数字).因此对于随机查找来说,比python自带的list快很多. 在numpy里面通常使用两个变量:array和matrix.其实python标准类库中也有array,但是它的功能相对numpy的少很多,所以不用.matrix是array的分支,matrix可以看做二维的array,array可以是多维,matrix和array在很多

矩阵相关知识

§1 矩阵及其运算 教学要求 : 理解矩阵的定义.掌握矩阵的基本律.掌握几类特殊矩阵(比如零矩阵,单位矩阵,对称矩阵和反对称矩阵 ) 的定义与性质.注意矩阵运算与通常数的运算异同.能熟练正确地进行矩阵的计算. 知识要点 : 一.矩阵的基本概念 矩阵,是由 个数组成的一个  行 列的矩形表格,通常用大写字母  表示,组成矩阵的每一个数,均称为矩阵的元素,通常用小写字母其元素  表示,其中下标  都是正整数,他们表示该元素在矩阵中的位置.比如, 或 表示一个 矩阵,下标 表示元素  位于该矩阵的第 

矩阵相关的小证明

$\forall A\in \mathbb{R}^{n\times n}$,$A^{\mathrm{T}}A$ 为半正定阵.\(\newcommand{\zz}[1]{#1^{\mathrm{T}}}\) \(\newcommand{\inprod}[2]{\langle#1\,,#2\rangle}\) 证明: 首先,不难证明,$\forall A\in \mathbb{R}^{m\times l}, B\in\mathbb{R}^{l\times n}, (AB)^\mathrm{T} =

理解CSS3 transform中的Matrix(矩阵)

一.哥,我被你吓住了 打架的时候会被块头大的吓住,学习的时候会被奇怪名字吓住(如“拉普拉斯不等式”).这与情感化设计本质一致:界面设计好会让人觉得这个软件好用! 所以,当看到上面“Matrix(矩阵)”的时候,难免会心生畏惧(即使你已经学过),正常心理.实际上,这玩意确实有点复杂. 然而,这却是屌丝逆袭的一个好机会. CSS同行间:你是不是有这样的感觉:哎呀呀,每天就是对着设计图切页面,貌似技术没有得到实质性地提升啊,或者觉得日后高度有限! 我们应该都知道二八法则(巴莱多定律),即任何一组东西中

【C++小白成长撸】--矩阵乘法程序

矩阵乘法是大学矩阵课程中,相比矩阵加减法比较困难的部分. 矩阵乘法的原理: 矩阵乘法在代码中实现 得到目标矩阵的一个元素,涉及两个求和符号,一个求和符号一个for循环,两个求和符号两个for循环,再加上是二维数组,再加一个for循环 以下呈现出代码 1 /*程序的版权和版本声明部分: 2 **Copyright(c) 2016,电子科技大学本科生二年级学生 3 **All rights reserved. 4 **文件名:矩阵乘法 5 **程序作用:矩阵乘法 6 **作者:Amoshen 7 *

css3 transform中的matrix矩阵

CSS3中的矩阵CSS3中的矩阵指的是一个方法,书写为matrix()和matrix3d(),前者是元素2D平面的移动变换(transform),后者则是3D变换.2D变换矩阵为3*3, 如上面矩阵示意图:3D变换则是4*4的矩阵. 有些迷糊?恩,我也觉得上面讲述有些不合时宜.那好,我们先看看其他东西,层层渐进——transform属性. 具体关于transform属性具体内容可以点击这里补个课.稍微熟悉的人都知道,transform中有这么几个属性方法: .trans_skew { trans

MyMathLib系列(矩阵算法--2)

矩阵相关的算法比较多,也是比较重要的,而且算法之间的性能差异确实比较大,初等变换法求逆比古典法求逆快不是一点点.矩阵的计算量和数值其实都是比较大的,特别是20阶以上,我在机器上最多只搞到40阶,随机产生的矩阵,很容易就爆掉decimal和double类型. 另外,这里使用了操作符重载,后面的一元符号运算也用到了操作符重载,后面如果有时间,我会将这些算法利用这些特性统一起来,本来它们的计算就应该是统一的.特别是符号运算.如果符号运算搞完,还可以试试自动命题证明玩玩. 好了,上矩阵的菜(有点长,但基

图片变换【Matrix】矩阵 简介

Matrix矩阵介绍 官方文档地址:https://developer.android.com/reference/android/graphics/Matrix.html 在Android中,对图片的处理需要使用到Matrix类,Matrix是一个3 x 3的矩阵,内部就是个一维数组,内部有9个元素,可以通过setValues(float[])进行初始化,通过getValues(float[])把拿到的矩阵值赋给传入的数组. 源码中的介绍就一句话:The Matrix class holds

[ css 矩阵 Matrix 属性 ] css中transform的Matrix(矩阵)属性讲解及实例演示的区别

一.哥,我被你吓住了 打架的时候会被块头大的吓住,学习的时候会被奇怪名字吓住(如“拉普拉斯不等式”).这与情感化设计本质一致:界面设计好会让人觉得这个软件好用! 所以,当看到上面“Matrix(矩阵)”的时候,难免会心生畏惧(即使你已经学过),正常心理.实际上,这玩意确实有点复杂. 然而,这却是屌丝逆袭的一个好机会. CSS同行间:你是不是有这样的感觉:哎呀呀,每天就是对着设计图切页面,貌似技术没有得到实质性地提升啊,或者觉得日后高度有限! 我们应该都知道二八法则(巴莱多定律),即任何一组东西中