[51nod - 1140] 矩阵相乘结果判定

题目:

给出三个 N×N N × N 的矩阵 A,B,C A , B , C ,问 A×B A × B 是否等于 C C

分析:

方法1
X=A×B,可以 O(N) O ( N ) 暴力算 Xi,j X i , j , 如果发现 Xi,jCi,j X i , j ≠ C i , j 则可直接判定不等。最坏复杂度 Θ(N3) Θ ( N 3 ) .

方法2
A×B=C A × B = C , 则对于任意一个 N N 维向量 V, 都有 V×A×B=V×C V × A × B = V × C 。那么我们可以随机生成一个向量 V V , O(N2)测试是否有 V×A×B=V×C V × A × B = V × C 即可,复杂度降为 O(N2) O ( N 2 ) ,但是有一定可能存在错判,可以通过多试几次来减少错判的可能性,总复杂度 O(CN2) O ( C N 2 ) ,其中 C C <script type="math/tex" id="MathJax-Element-2628">C</script> 为测试次数。

在精度要求不是很严格的条件下,方法2显然是更优的,对于可以重复提交的算法竞赛中,可以使用这个方法来降低复杂度。

代码:

#include <bits/stdc++.h>

using namespace std;

const int N_MAX = 501;
int n;
struct Mat {
  int mat[N_MAX][N_MAX];
  int N, M;
  bool operator ==(const Mat& rhs) const {
    for (int i = 1; i <= N; i++) {
      for (int j = 1; j <= M; j++) {
        if (mat[i][j] != rhs.mat[i][j]) return false;
      }
    }
    return true;
  }

  void init(int n, int m) {
    N = n;
    M = m;
  }
  void read() {
    for (int i = 1; i <= N; i++) {
      for (int j = 1; j <= N; j++) {
        scanf("%d", mat[i] + j);
      }
    }
  }

  void gen() {
    for (int i = N; i <= M; i++) {
      for (int j = 1; j <= M; j++) {
        mat[i][j] = rand() % 10 + 1;
      }
    }
  }
}arr[4];
Mat mul(const Mat& lhs, const Mat& rhs) {
  assert(lhs.M == rhs.N);
  Mat ret;
  ret.init(lhs.N, rhs.M);
  for (int i = 1; i <= lhs.N; i++) {
    for (int j = 1; j <= rhs.M; j++) {
      ret.mat[i][j] = 0;
      for (int k = 1; k <= lhs.M; k++) {
        ret.mat[i][j] += lhs.mat[i][k] * rhs.mat[k][j];
      }
    }
  }
  return ret;
}
const double lim = 0.7;

inline bool check() {
  return mul(mul(arr[3], arr[0]), arr[1]) == mul(arr[3], arr[2]);
}
int main() {
  srand(time(0));
  scanf("%d", &n);
  for (int i = 0; i < 3; i++) {
    arr[i].init(n, n);
    arr[i].read();
  }
  arr[3].init(1, n);
  while (double(clock()) / CLOCKS_PER_SEC < lim) {
    arr[3].gen();
    if (!check()) {
      puts("No");
      return 0;
    }
  }
  puts("Yes");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值