1404. 【中山市选2008】矩阵

题目

输入 

 输出

样例输入

2
2
10
01
11
10
11
01
3
111
111
000
100
010
001
111
111
000

样例输出

NO
YES

思路 

        本题如果我们用暴力做法,时间复杂度为O(n^3),会TLE。

        首先,我们知道等式两边同时乘一个数,等式仍然成立。

        而这个定理在等式中仍然成立,我们折A*B=C,则A*B*D=C*D。(A,B,C,D均为矩阵)。

        前提是:A是M列,B和D都是M行。

        所以,我们可以优化我们的暴力。我们设D为N行一列,题目即可变为判断A*B*D=C*D是否成立。然后再使用一个乘法结合律,把A*B*D变为A*(B*D)。

        然后我们来看一下时间复杂度

        E=B*D(O(N^2))

        F=A*E(O(N^2))

        G=C*D(O(N^2))

        由于这题是01矩阵,1+1=0,所以需要用到位运算。

        而且,可能原本不相等的,乘了个D就相等了。

        所以我们随机生成10次D,不相等直接输出NO,否则输出YES。

具体代码

#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,t,bz=1,a[1005][1005],b[1005][1005],c[1005][1005],x[1005],y[1005],z[1005],f[1005];
int main()
{
    srand(time(NULL));
    scanf("%d",&t);
    for (int q=1;q<=t;q++)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                scanf("%1d",&a[i][j]);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                scanf("%1d",&b[i][j]);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                scanf("%1d",&c[i][j]);
        bz=1;
        for (int p=1;p<=10;p++)
        {
            for (int i=1;i<=n;i++)
                f[i]=rand()%2+0;
            memset(x,0,sizeof(x));
            memset(y,0,sizeof(y));
            memset(z,0,sizeof(z));
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                    x[i]=x[i]^(b[i][j]&f[j]);
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                    y[i]=y[i]^(a[i][j]&x[j]);
            for (int i=1;i<=n;i++)
                for (int j=1;j<=n;j++)
                    z[i]=z[i]^(c[i][j]&f[j]);
            for (int i=1;i<=n;i++)
            {
                if (y[i]!=z[i])
                {
                    bz=0;
                    printf("NO\n");
                    break;
                }
            }
            if (bz==0) break;
        }
        if (bz==1) printf("YES\n");
    }
    return 0;
 } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值