洛谷 P3390 [模板] 矩阵快速幂 题解

【模板】矩阵快速幂

题目背景

一个 m × n m \times n m×n矩阵是一个由 m m m n n n 列元素排列成的矩形阵列。即形如

A = [ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯ a m n ] . A = \begin{bmatrix} a_{1 1} & a_{1 2} & \cdots & a_{1 n} \\ a_{2 1} & a_{2 2} & \cdots & a_{2 n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m 1} & a_{m 2} & \cdots & a_{m n} \end{bmatrix} \text{.} A= a11a21am1a12a22am2a1na2namn .

本题中认为矩阵中的元素 a i j a_{i j} aij 是整数。

两个大小分别为 m × n m \times n m×n n × p n \times p n×p 的矩阵 A , B A, B A,B 相乘的结果为一个大小为 m × p m \times p m×p 的矩阵。将结果矩阵记作 C C C,则

c i j = ∑ k = 1 n a i k b k j , ( 1 ≤ i ≤ m ,  1 ≤ j ≤ p ). c_{i j} = \sum_{k = 1}^{n} a_{i k} b_{k j} \text{,\qquad($1 \le i \le m$, $1 \le j \le p$).} cij=k=1naikbkj,(1im, 1jp).

而如果 A A A 的列数与 B B B 的行数不相等,则无法进行乘法。

可以验证,矩阵乘法满足结合律,即 ( A B ) C = A ( B C ) (A B) C = A (B C) (AB)C=A(BC)

一个大小为 n × n n \times n n×n 的矩阵 A A A 可以与自身进行乘法,得到的仍是大小为 n × n n \times n n×n 的矩阵,记作 A 2 = A × A A^2 = A \times A A2=A×A。进一步地,还可以递归地定义任意高次方 A k = A × A k − 1 A^k = A \times A^{k - 1} Ak=A×Ak1,或称 A k = A × A × ⋯ × A ⏟ k  次 A^k = \underbrace{A \times A \times \cdots \times A}_{k \text{ 次}} Ak=k  A×A××A

特殊地,定义 A 0 A^0 A0 为单位矩阵 I = [ 1 0 ⋯ 0 0 1 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ 1 ] I = \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix} I= 100010001

题目描述

给定 n × n n\times n n×n 的矩阵 A A A,求 A k A^k Ak

输入格式

第一行两个整数 n , k n,k n,k
接下来 n n n 行,每行 n n n 个整数,第 i i i 行的第 j j j 的数表示 A i , j A_{i,j} Ai,j

输出格式

输出 A k A^k Ak

n n n 行,每行 n n n 个数,第 i i i 行第 j j j 个数表示 ( A k ) i , j (A^k)_{i,j} (Ak)i,j,每个元素对 1 0 9 + 7 10^9+7 109+7 取模。

样例 #1

样例输入 #1

2 1
1 1
1 1

样例输出 #1

1 1
1 1

提示

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100 1\le n \le 100 1n100 0 ≤ k ≤ 1 0 12 0 \le k \le 10^{12} 0k1012 ∣ A i , j ∣ ≤ 1000 |A_{i,j}| \le 1000 Ai,j1000

原题

洛谷P3390——传送门

代码

#include <bits/stdc++.h>
using namespace std;
#define max_Heap(x) priority_queue<x, vector<x>, less<x>>
#define min_Heap(x) priority_queue<x, vector<x>, greater<x>>
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
const double PI = acos(-1);

const int mod = 1e9 + 7; // 模数
struct Matrix            // 矩阵结构体
{
    ll m[106][106]; // 开longlong
};
Matrix a, e; // a输入矩阵,e单位矩阵
ll n, p;
Matrix Mul(Matrix x, Matrix y) // 矩阵相乘
{
    Matrix res;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            res.m[i][j] = 0;    //非全局定义的变量需初始化
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++)
            {
                res.m[i][j] += x.m[i][k] * y.m[k][j];
                res.m[i][j] %= mod;
            }
    return res;
}
Matrix qpow(Matrix x, ll y) // 矩阵快速幂
{
    Matrix res = e;
    while (y)
    {
        if (y & 1)
        {
            res = Mul(res, x);
        }
        x = Mul(x, x);
        y >>= 1;
    }
    return res;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    // 输入
    cin >> n >> p;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> a.m[i][j];
        }
    }
    // 单位矩阵初始化
    for (int i = 1; i <= n; i++)
    {
        e.m[i][i] = 1;
    }
    Matrix ans = qpow(a, p);
    // 输出
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (j != n)
                cout << (ans.m[i][j] + mod) % mod << ' ';
            else
                cout << (ans.m[i][j] + mod) % mod << '\n';
        }
    }
    return 0;
}
  • 28
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值