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

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

Description

  • 给定n*n的矩阵A,求A^k
  • n<=100, k<=10^12, |矩阵元素|<=1000

Input

  • 第一行,n,k

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

Output

  • 输出A^k

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

Sample Input

2 1
1 1
1 1

Sample output

1 1
1 1

题解:

  • 算法如题所示。

  • 矩阵是什么?

    • 就是一个矩阵,字面意思。
  • 矩阵如何运算?

    1. 加法:对于两个形一样的矩阵,对应的位置相加就好了
    2. 减法:同加法一样
    3. 除法:貌似实际中是有的,但是OI中不常用,不讨论
    4. 乘法:矩阵乘法是重头戏,她有个前提条件,两个矩阵相乘,必须满足(n, m) * (m, p) = (n, p)。(前一个个数是行,后一个数是列)。就像这样↓(2, 2) * (2, 1) = (2, 1)

\[ \left\{ \begin{matrix} 1 & 1 \\ 0 & 3 \\ \end{matrix} \right\} * \left\{ \begin{matrix} 2 \\ 2 \\ \end{matrix} \right\} = \left\{ \begin{matrix} 1 * 2 + 1 * 2 \\ 0 * 2 + 3 * 2 \\ \end{matrix} \right\} \]

\[ \left[ \begin{matrix} 2 \\ 2 \\ \end{matrix} \right] * \left[ \begin{matrix} 1 & 1 \\ 0 & 3 \\ \end{matrix} \right] != \left[ \begin{matrix} 1 * 2 + 1 * 2 \\ 0 * 2 + 3 * 2 \\ \end{matrix} \right] 但这样写就是错的! \]

  • 因为(2, 1) * (2, 2)。1 != 2,不符合矩阵乘法意义。

    • 所以由此还可以推出:矩阵不满足交换律
  • 矩阵有什么用?

    • 优化递推式。
    • 我怎么知道什么时候要优化递推式?
      • 数据范围极大,比如10的18次方什么的,O(n)都过不去的
    • 怎么优化?
    • 一般优化就是优化在矩阵快速幂上,但写完快速幂之后怎么优化,转这里
    • 所以现在任务就是写矩阵快速幂!
  • 矩阵快速幂:

    • 首先易得矩阵乘法是满足结合律的,所以快速幂的跟普通的快速幂没有什么区别,直接给出代码,细细品味一下。(反正我看了一篇大概就懂了)
    #include <iostream>
    #include <cstdio>
    #define maxn 105
    #define mod 1000000007
    #define LL long long
    using namespace std;
    
    struct Obj {LL a[maxn][maxn];} x, d;
    LL n, p;
    
    Obj mul(Obj x, Obj y)
    {
      Obj r;
      for(LL i = 1; i <= n; i++)
          for(LL j = 1; j <= n; j++)
              r.a[i][j] = 0;
      for(LL i = 1; i <= n; i++)
          for(LL j = 1; j <= n; j++)
              for(LL k = 1; k <= n; k++)
                  r.a[i][j] += (x.a[i][k] % mod * y.a[k][j] % mod) % mod,
                  r.a[i][j] %= mod;
      return r;
    }
    
    Obj power(Obj x, LL p)
    {
      Obj r = d, base = x;
      while(p)
      {
          if(p & 1) r = mul(r, base);
          base = mul(base, base);
          p >>= 1;
      }
      return r;
    }
    
    int main()
    {
      cin >> n >> p;
      for(LL i = 1; i <= n; i++)
          for(LL j = 1; j <= n; j++)
              cin >> x.a[i][j];
      for(LL i = 1; i <= n; i++) d.a[i][i] = 1;
      Obj ans = power(x, p);
      for(LL i = 1; i <= n; i++)
      {
          for(LL j = 1; j <= n; j++)
              cout << ans.a[i][j] % mod << ' ';
          cout << endl;
      }
      return 0;
    }

猜你喜欢

转载自www.cnblogs.com/BigYellowDog/p/11203363.html