作为一个因为极度畏惧数学

而选择成为一名OIer的蒟蒻

终于还是迎来了要面对的这一天


一般题目中矩阵运算好像只用到矩阵乘法

(或许只是蒟蒻我做的题太少)

而且矩阵的乘法也是较难理解的一部分

所以就简单讲讲矩阵乘法

如图

矩阵A*B就是用A的每一行依次乘B的每一列

具体就是A的第i行中每一个数对应相乘B的第j列每个数

每个相乘所得结果相加

最后放置于C矩阵的第i行第j号位

所以矩阵乘法中A的列数必须等于B的行数

(虽然第一次看确实有些绕,但它用起来真的妙啊~妙啊~)

上一个矩阵A*B的代码

(这里以正方形矩阵为例)

for(ll i=1;i<=n;i++)//枚举A的每一行
for(ll j=1;j<=n;j++)//枚举B的每一列
for(ll k=1;k<=n;k++)//k既是A的列数,也是B的行数
C.a[i][j]+=A.a[i][k]*B.a[k][j];

这里运算的复杂度为O(n^3)

一般题目已经够用

有O(n^2.7)的算法太 太 太复杂

所以其实可以不用在意的啦

神奇的一点

矩阵乘法也是支持结合律的!!!

但是它不支持分配律

这是很重要的一点

因为这决定了他也同样可以快速幂

(你别告诉我不知道快速幂是什么 = = )

所以就先上一道最最基础的矩阵运算入门操作

题目传送门 啦~啦~啦~


题目描述

给定n*n的矩阵A,求A^k

输入输出格式

输入格式:

第一行,n,k

第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素

输出格式:

输出A^k

共n行,每行n个数,第i行第j个数表示矩阵第i行第j列的元素,每个元素模10^9+7

输入样例

2 1

1 1

1 1

输出样例

1 1

1 1

说明

n<=100, k<=10^12, |矩阵元素|<=1000


这次具体解释看代码注释啦~啦~啦~

(不要吐槽我的蜜汁缩进)

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;

ll read()
{
    ll f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return x*f;
}

void print(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

ll n,m;
ll ans;
const ll mod=1000000000+7;
struct node{ll a[110][110];}d;
//用结构体储存矩阵,以便调用快速幂后返回整个矩阵

node quick_pow(node f,ll k)
{
    if(k==1) return f;
    //若指数为1,则直接返回矩阵

    else if(k%2==1)
    {
        //指数为奇数,返回k-1次方乘一次方
        node temp=quick_pow(f,k-1);
        node ans;
        for(ll i=1;i<=n;i++)
        for(ll j=1;j<=n;j++)
        for(ll k=1;k<=n;k++)
        ans.a[i][j]+=(f.a[i][k]*temp.a[k][j])%mod,ans.a[i][j]%=mod;
        return ans;
    }

    else if(k%2==0)
    {
        //指数为偶数,计算矩阵的k/2次方,在返回平方
        node temp=quick_pow(f,k/2);
        node ans;
        for(ll i=1;i<=n;i++)
        for(ll j=1;j<=n;j++)
        for(ll k=1;k<=n;k++)
        ans.a[i][j]+=(temp.a[i][k]*temp.a[k][j])%mod,ans.a[i][j]%=mod;
        return ans;
    }
}

int main()
{
    n=read();m=read();
    for(ll i=1;i<=n;i++)
    for(ll j=1;j<=n;j++)
    d.a[i][j]=read();//读入初始矩阵

    node ans=quick_pow(d,m);//快速幂

    for(ll i=1;i<=n;i++)
    {
        for(ll j=1;j<=n;j++)
        print(ans.a[i][j]),printf(" ");
        printf("\n");
    }
    return 0;
}

洛谷P3390【模板】矩阵快速幂——矩阵运算入门笔记的更多相关文章

  1. 【洛谷P3390】矩阵快速幂

    矩阵快速幂 题目描述 矩阵乘法: A[n*m]*B[m*k]=C[n*k]; C[i][j]=sum(A[i][1~n]+B[1~n][j]) 为了便于赋值和定义,我们定义一个结构体储存矩阵: str ...

  2. 3990 [模板]矩阵快速幂 洛谷luogu

    题目背景 矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 输入输出格式 输入格式: 第一行,n,k 第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素 输出格式: 输出A^k ...

  3. ACM-ICPC 2018 焦作赛区网络预赛- L:Poor God Water(BM模板/矩阵快速幂)

    God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him t ...

  4. 【洛谷 p3390】模板-矩阵快速幂(数论)

    题目:给定n*n的矩阵A,求A^k. 解法:利用矩阵乘法的定义和快速幂解答.注意用负数,但是数据太弱没有卡到我......(P.S.不要在 typedef long long  LL; 前使用 LL. ...

  5. 洛谷 P1965 转圈游戏 —— 快速幂

    题目:https://www.luogu.org/problemnew/show/P1965 居然真的就只是 ( x + m * 10k % n ) % n 代码如下: #include<ios ...

  6. POJ 3070 Fibonacci 矩阵快速幂模板

    Fibonacci Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18607   Accepted: 12920 Descr ...

  7. 模板【洛谷P3390】 【模板】矩阵快速幂

    P3390 [模板]矩阵快速幂 题目描述 给定n*n的矩阵A,求A^k 矩阵A的大小为n×m,B的大小为n×k,设C=A×B 则\(C_{i,j}=\sum\limits_{k=1}^{n}A_{i, ...

  8. 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线

    P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...

  9. 洛谷P1939【模板】矩阵加速(数列)+矩阵快速幂

    思路: 这个 a[1]=a[2]=a[3]=1 a[x]=a[x-3]+a[x-1] (x>3) 可以想成: [a(n) ] [1 0 1] [a(n-1)   ] [a(n-1) ] =    ...

随机推荐

  1. Android + Eclipse + PhoneGap 环境配置

    用了3天的时间,终于把环境搭建完毕,郁闷了N天,终于完成了.这里我只是讲述我安装的过程,仅供大家参考. 环境搭建首先要去下载一些安装包: (下载前注意一下,电脑是32位还是64位的请注意选择安装包) ...

  2. nodejs+websocket实时聊天系统

    介绍下websocket: webSocket协议本质上是一个基于tcp的协议; 建立一个websocket连接,大体的过程: 1.客户端浏览器首先向服务器发起一个http请求,这个请求和平常的请求有 ...

  3. fread读取文件(二进制文件)

    fread()是c库函数,利于移植,使用缓存,效率较read()高. 原型: size_t fread(void *buffer, size_t size, size_t count, FILE * ...

  4. Python--socketserve源码分析(二)

    BaseServer::self.process_request(request, client_address) 实现原理: 在类的继承关系中,当子类中没有相应的方法时就会去父类中寻找, 当继承多个 ...

  5. 流API--流的映射

    很多时候,将一个流的元素映射到另外一个流很有帮助.映射操作最具代表的就是map()方法.实际编码中,我们会经常用到,所以这里专门整理一篇博客. 考虑如下情景,对于一个包含了姓名,电话,年龄等属性构成的 ...

  6. SQL语句-create语句

    SQL语法基础 Create database语句 Create database语句是在MySQL实例上创建一个指定名称的数据 库,create schema语句的语义和create databas ...

  7. 面试中的TCP协议

    TCP的三次握手和四次挥手 三次握手 TCP连接是通过三次握手来连接的. 第一次握手 当客户端向服务器发起连接请求时,客户端会发送同步序列标号SYN到服务器,在这里我们设SYN为x,等待服务器确认,这 ...

  8. 《.NET 设计规范》第 3 章 命名规范

    <.NET 规范>第 3 章 命名规范 3.1 大小写约定 要把 PascalCasing 用于由多个单词构成的命名空间.类型以及成员的名字. 要把 camelCasing 用于参数的名字 ...

  9. [DeeplearningAI笔记]ML strategy_2_2训练和开发/测试数据集不匹配问题

    机器学习策略-不匹配的训练和开发/测试数据 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.4在不同分布上训练和测试数据 在深度学习时代,越来越多的团队使用和开发集/测试集不同分布的数据来 ...

  10. ORACLE 建表语句(表名及字段名大写)

    ORACLE建表时如果表名或者字段名存在大小写同时存在的情况下,默认为区分大小写,此时在select/updata等操作时需要在表名或者字段名上添加双引号,否则会报"视图不存在"的 ...