P3390 矩阵快速幂

P3390 矩阵快速幂

题目出处

题目描述

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

输入格式

第一行两个整数n k接下来n行每行n个整数, 第i行的第j的数表示A[i,j]

输出格式

输出A^kn行,每行n个数, 第i行第j个数表示A^k[i,j], 每个元素对10^9+7取模

输入输出样例

In

2 1
1 1
1 1

Out

1 1
1 1

题解

思路

既然是快速幂, 那肯定和普通快速幂是一样的原理, 将指数分解, 然后用O(log k)的复杂度计算最后的结果

矩阵乘法规则

定义n*p的矩阵和p*m的矩阵的乘法运算

\[A*B=C \]

C为n*m的矩阵

矩阵每个元素的规则为:

\[C_{i,j}=\sum^{k=1}_{k<=p}{A_{i,k}*B_{k,j}} \]

一般快速幂

幂运算的基本性质

\[a^{n+m}=a^{n}*a^{m} \]

得到特殊情况的推论

\[a^{2n}=a^{n^{2}} \\ a^{2n+1}=a^{n^{2}}*n \]

所以a的n次幂可以这样一直分解, 直到n=1或n=0的时候

由于矩阵乘法遵循结合率, 所以矩阵也可以这样求n次幂

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
struct Matrix {//矩阵结构体
  long long a[105][105];
} mtx;
long long k, N;//k次幂, 矩阵大小N*N
Matrix operator*(Matrix x, Matrix y) {//重载矩阵乘法运算符
  Matrix ans;
  long long tmp;
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      for (int k = 1; k <= N; k++) {
        tmp = x.a[k][j] * y.a[i][k];
        tmp %= 1000000007;
        ans.a[i][j] += tmp;
        ans.a[i][j] %= 1000000007;
      }
    }
  }
  return ans;//返回一个矩阵
}
void print(Matrix x) {//输出矩阵x
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      printf("%lld ", x.a[i][j]);
    }
    printf("\n");
  }
  return;
}
Matrix power(Matrix x, long long y) {//计算矩阵x的y次幂
  Matrix ans;
  if (y == 0) {//单位矩阵, 作为任何矩阵的0次幂
    for (int i = 1; i <= N; i++) {
      for (int j = 1; j <= N; j++) {
        if (i == j) {
          ans.a[i][j] = 1;
        } else {
          ans.a[i][j] = 0;
        }
      }
    }
    return ans;
  }
  if (y == 1) {//一次方是x本身
    return x;
  }
  if (y == 2) {//二次方直接平方
    return (x * x);
  }
  if (y % 2) {  //奇次幂
    ans = power(x, y >> 1);
    return ans * ans * x;
  } else {//偶次幂
    ans = power(x, y >> 1);
    return ans * ans;
  }
  return ans;
}
int main() {
  scanf("%lld%lld", &N, &k);
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      scanf("%lld", &mtx.a[i][j]);
    }
  }//读入矩阵
  print(power(mtx, k));
  return 0;
}
posted @ 2020-06-17 16:59  Wild_Donkey  阅读(139)  评论(0编辑  收藏  举报