题目:
给出三个 N×NN×N的矩阵 A,B,CA,B,C,问A×BA×B是否等于CC?
分析:
方法1
设 ,可以O(N)O(N) 暴力算 Xi,jXi,j, 如果发现 Xi,j≠Ci,jXi,j≠Ci,j 则可直接判定不等。最坏复杂度 Θ(N3)Θ(N3).
方法2
若 A×B=CA×B=C, 则对于任意一个 NN 维向量 , 都有 V×A×B=V×CV×A×B=V×C。那么我们可以随机生成一个向量 VV, 测试是否有 V×A×B=V×CV×A×B=V×C 即可,复杂度降为 O(N2)O(N2),但是有一定可能存在错判,可以通过多试几次来减少错判的可能性,总复杂度 O(CN2)O(CN2),其中 CC 为测试次数。
在精度要求不是很严格的条件下,方法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");
}