Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 18463 | Accepted: 3978 |
Description
You are given three n × n matrices A, B and C. Does the equation A × B = C hold true?
Input
The first line of input contains a positive integer n (n ≤ 500) followed by the the three matrices A, B and C respectively. Each matrix's description is a block of n × n integers.
It guarantees that the elements of A and B are less than 100 in absolute value and elements of C are less than 10,000,000 in absolute value.
Output
Output "YES" if the equation holds true, otherwise "NO".
Sample Input
2 1 0 2 3 5 1 0 8 5 1 10 26
Sample Output
YES
Hint
Source
题目大意:
给三个比较大的矩形,判断前两个的乘积是不是第三个。
解题思路:
题目的hint明确说明了O(n^3)的方法会TLE,我试了一下,即使加优化也确实是TLE了,O(n^2.7)的写法没试,估计也过不了。
既然常规方法写不了,我们就可以用随机化算法来求解了。由矩阵乘法的性质可以得到:A*B*X==C*X <==> A*B==C 。如果我们令X向量是一个N阶列向量,并且先算B*X,就可以把复杂度降为O(N^2),但是这样并不是一定正确的,虽然正确率比较高。于是我们就可以重复多次随机生成X向量,这样的成功率就非常高了(概率的证明有点长,这里就不写了)。
不知道为什么在POJ上提交G++是RE,C++是AC,在51node上是AC。
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;
#define mem(a,b) memset((a),(b),sizeof(a))
const int MAXN=500+3;
int N,a[3][MAXN][MAXN],l[MAXN],ll[MAXN],r[MAXN],X[MAXN];
int main()
{
srand((int)time(NULL));
while(~scanf("%d",&N))
{
for(int i=0;i<3;++i)//输入开始的三个矩阵
for(int j=0;j<N;++j)
for(int k=0;k<N;++k)
scanf("%d",&a[i][j][k]);
int times=10;//随机10次
bool ans=true;
while(times>0)
{
mem(l,0);
mem(ll,0);
mem(r,0);
for(int i=0;i<N;++i)//随机构造用来检测的矩阵X
X[i]=rand()%100;
for(int i=0;i<N;++i)//计算B*X
for(int j=0;j<N;++j)
l[i]+=X[j]*a[1][i][j];
for(int i=0;i<N;++i)//计算A*(B*X)
for(int j=0;j<N;++j)
ll[i]+=l[j]*a[0][i][j];
for(int i=0;i<N;++i)//计算C*X
for(int j=0;j<N;++j)
r[i]+=X[j]*a[2][i][j];
bool ok=true;
for(int i=0;i<N;++i)
if(ll[i]!=r[i])
{
ok=false;
break;
}
if(!ok)
{
ans=false;
break;
}
--times;
}
puts(ans?"YES":"NO");
}
return 0;
}