POJ 3338 Matrix Multiplication(随机化算法)

Matrix Multiplication
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 18463 Accepted: 3978

Description

You are given three n × n matrices AB 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 AB and 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

Multiple inputs will be tested. So O(n 3) algorithm will get TLE.

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值