• 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("
    ");
      }
      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;
    }
    
  • 相关阅读:
    20201215王馨瑶 实验一《Python程序设计》实验报告
    20201215第十六周学习总结
    python笔记
    信导笔记
    成绩调节
    2020-2021-1 20201226 《信息安全专业导论》第十三周学习总结
    链表(补交)
    2020-2021-1 20201226 《信息安全专业导论》第十二周学习总结
    Wireshark 实践
    ssh
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/13153424.html
Copyright © 2020-2023  润新知