Problem
神奇的矩阵
Time Limit: 5Sec
Memory Limit: 512MB
Description
给出三个行数和列数均为N的矩阵A、B、C,判断A×B=C是否成立。
题目可能包含若干组数据。
对于每组数据,第一行一个数N,接下来给出三个N×N的矩阵,依次为A、B、C三个矩阵。
Output
对于每组数据,若A×B=C成立,则输出Yes,否则No。每个答案占一行。
Sample Output
HINT
对于90%的数据,N不超过100;
对于100%的数据,N不超过1000,矩阵中的数字大于等于0小于1000,数据组数不超过5组。
标签:矩阵乘法
随机化
Solution
挺巧妙的一道随机化题。
首先考虑直接乘,由于N≤1000,而矩乘是O(n3),肯定会TLE。
我们发现矩阵太大了,那么我们就要压缩矩阵,把这样一个正方形的矩阵压缩为一个行矩阵或列矩阵。
我们先随机出一个1×n的列矩阵R,这样A×B×R=A×(B×R),将结果与C×R比较。这样乘法的复杂度就降为O(n2),比较复杂度为O(n),总复杂度为O(n2)。如果觉得随机一次不保险,还可以多随机几次,不过只随一次也很容易过。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <bits/stdc++.h> #define MAX_N 1000 #define MOD 1000000007 using namespace std; int n; struct Matrix { int r, c; long long ele[MAX_N][MAX_N]; inline Matrix operator * (const Matrix &x) const { Matrix ret; memset(ret.ele, 0, sizeof(ret.ele)); for (int i = 0; i < (ret.r = r); i++) for (int j = 0; j < (ret.c = x.c); j++) for (int k = 0; k < c; k++) ret.ele[i][j] = (ret.ele[i][j]+ele[i][k]*x.ele[k][j])%MOD; return ret; } } A, B, C, R; int main() { while (scanf("%d", &n)) { A.r = A.c = n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) scanf("%lld", &A.ele[i][j]); B.r = B.c = n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) scanf("%lld", &B.ele[i][j]); C.r = C.c = n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) scanf("%lld", &C.ele[i][j]); srand(19260817); R.r = n, R.c = 1; for (int i = 0; i < n; i++) R.ele[i][0] = rand()*rand()%MOD; A = A*(B*R), C = C*R; bool flag = true; for (int i = 0; i < n; i++) flag &= (A.ele[i][0] == C.ele[i][0]); puts(flag ? "Yes" : "No"); } return 0; }
|