题目:
给出三个 N×N N × N 的矩阵 A,B,C A , B , C ,问 A×B A × B 是否等于 C C ?
分析:
方法1
设 ,可以
O(N)
O
(
N
)
暴力算
Xi,j
X
i
,
j
, 如果发现
Xi,j≠Ci,j
X
i
,
j
≠
C
i
,
j
则可直接判定不等。最坏复杂度
Θ(N3)
Θ
(
N
3
)
.
方法2
若
A×B=C
A
×
B
=
C
, 则对于任意一个
N
N
维向量 , 都有
V×A×B=V×C
V
×
A
×
B
=
V
×
C
。那么我们可以随机生成一个向量
V
V
, 测试是否有
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");
}