2 条题解

  • 0
    @ 2025-7-27 10:37:40

    不使用快速幂的标准方法

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    
    const ll MOD = 1000000007;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int n;
        ll k;
        cin >> n >> k;
    
        // 读入原矩阵 A,注意取模并处理可能的负数
        vector<vector<ll>> A(n, vector<ll>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                ll x;
                cin >> x;
                // 统一转为 [0, MOD) 范围内
                A[i][j] = (x % MOD + MOD) % MOD;
            }
        }
    
        // 如果 k == 0,A^0 定义为单位矩阵 I
        vector<vector<ll>> result(n, vector<ll>(n, 0));
        for (int i = 0; i < n; i++) {
            result[i][i] = 1;
        }
    
        // 普通矩阵乘法重复 k 次,得到 A^k
        // 每一次: result = result * A
        vector<vector<ll>> tmp(n, vector<ll>(n));
        for (ll step = 0; step < k; step++) {
            // 清空 tmp,用于存放这一次的乘积
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    tmp[i][j] = 0;
                }
            }
            // 三重循环完成矩阵乘法
            // tmp[i][j] = sum_{l=0..n-1} result[i][l] * A[l][j]
            for (int i = 0; i < n; i++) {
                for (int l = 0; l < n; l++) {
                    if (result[i][l] == 0) continue;  // 小优化:跳过零元素
                    ll v = result[i][l];
                    for (int j = 0; j < n; j++) {
                        tmp[i][j] = (tmp[i][j] + v * A[l][j]) % MOD;
                    }
                }
            }
            // 将 tmp 复制回 result,为下一轮做准备
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    result[i][j] = tmp[i][j];
                }
            }
        }
    
        // 输出结果矩阵 result,即 A^k mod 10^9+7
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cout << result[i][j] << (j + 1 == n ? '\n' : ' ');
            }
        }
    
        return 0;
    }
    
    
    • 0
      @ 2025-7-22 16:41:21

      矩阵快速幂自己方法:

      #include <bits/stdc++.h>
      using namespace std;
      using ll = long long;
      const ll MOD = 1000000007;  // 模数 10^9+7
      
      // 动态数组矩阵类型,大小 n×n
      using mat = vector<vector<ll>>;
      
      /// 矩阵乘法:返回 C = A * B (均为 n×n 矩阵)
      /// 时间复杂度 O(n^3)
      mat mmul(const mat &A, const mat &B) {
          int n = A.size();
          mat C(n, vector<ll>(n, 0));  // 动态分配结果矩阵并初始化为 0
          // 三层循环实现:按行×列
          for (int i = 0; i < n; i++) {
              for (int k = 0; k < n; k++) {
                  ll v = A[i][k];
                  if (v == 0) continue;  // 跳过 0 可以加速
                  for (int j = 0; j < n; j++) {
                      // C[i][j] += A[i][k] * B[k][j],并取模防止溢出
                      C[i][j] = (C[i][j] + v * B[k][j]) % MOD;
                  }
              }
          }
          return C;
      }
      
      /// 快速矩阵幂:返回 A^e (n×n 矩阵)
      /// 核心:二进制快速幂,把指数 e 拆成二进制位
      mat mpow(mat A, ll e) {
          int n = A.size();
          // 初始化结果为单位矩阵 I_n
          mat R(n, vector<ll>(n, 0));
          for (int i = 0; i < n; i++) {
              R[i][i] = 1;
          }
          // 当 e > 0 时循环
          while (e > 0) {
              if (e & 1) {
                  // 当前位为 1,就用 R = R * A
                  R = mmul(R, A);
              }
              // A 自身平方:A = A * A
              A = mmul(A, A);
              // 处理下一位
              e >>= 1;
          }
          return R;
      }
      
      int main() {
          ios::sync_with_stdio(false);
          cin.tie(nullptr);
      
          int n;
          ll k;
          cin >> n >> k;
          // 读入原矩阵 A,使用动态数组(vector)存储
          mat A(n, vector<ll>(n));
          for (int i = 0; i < n; i++) {
              for (int j = 0; j < n; j++) {
                  cin >> A[i][j];
                  // 取模并处理负数
                  A[i][j] %= MOD;
                  if (A[i][j] < 0) A[i][j] += MOD;
              }
          }
      
          // 计算 A^k
          mat B = mpow(A, k);
      
          // 输出结果矩阵
          for (int i = 0; i < n; i++) {
              for (int j = 0; j < n; j++) {
                  cout << B[i][j] << (j + 1 < n ? ' ' : '\n');
              }
          }
          return 0;
      }
      
      • 1

      信息

      ID
      1133
      时间
      1000ms
      内存
      256MiB
      难度
      9
      标签
      递交数
      14
      已通过
      3
      上传者