【中山市选2008】矩阵

来源:互联网 发布:新网域名管理后台 编辑:程序博客网 时间:2024/04/29 07:45

【中山市选2008】矩阵


Description
题目描述

Input
输入

Output
输出

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

Sample Output
NO
YES


题目大意

已知三个01矩阵ABC,问A*B是否等于C

说一下矩阵乘法的运算:

C[i,j]=k=1nA[i,k]B[k,j]

那么01矩阵乘法:
C[i,j]=Xornk=1A[i,k]andB[k,j]


解题思路

我们可以将每一行想象成二进制数,令A[i,j]表示A矩阵第i行第j个数,B[i]表示B矩阵第i行的二进制数,Ans[i]表示两矩阵相乘后结果第i行的二进制数,易得:

Ans[i]=Xornj=1(A[i,j]=1)B[j]

但是,n大于64时B和Ans就撑不下了,所以我们要打高精度压位:

Codes:

const    maxn=25;var    a,b,c,ans:array[1..1000,0..1500]of longint;    bz:array[1..1000]of boolean;    n,ca,i,o,j,x,l:longint;    ch:char;    p:boolean;function max(p,q:longint):longint;begin    if p>q then exit(p) else exit(q);end;procedure add(x,y:longint);    var o:longint;begin    for o:=1 to (n+maxn-1)div maxn do        ans[x,o]:=ans[x,o] xor b[y,o];end;procedure doit; //求正确答案    var i,j:longint;begin    fillchar(ans,sizeof(ans),0);    for i:=1 to n do        for j:=1 to n do            if a[i,j]=1 then add(i,j);end;begin    read(ca);    for o:=1 to ca do    begin        readln(n);        fillchar(b,sizeof(b),0);        fillchar(c,sizeof(c),0);        for i:=1 to n do        begin            for j:=1 to n do            begin                read(ch);                a[i,j]:=ord(ch)-48;            end;            readln;        end;        for i:=1 to n do        begin            for j:=1 to n do            begin                read(ch);                inc(b[i,(j+maxn-1)div maxn],(ord(ch)-48)<<(j mod maxn));  //转成十进制并且压位            end;            readln;        end;        for i:=1 to n do        begin            for j:=1 to n do            begin                read(ch);                inc(c[i,(j+maxn-1)div maxn],(ord(ch)-48)<<(j mod maxn));            end;            readln;        end;        doit;        p:=false;        for i:=1 to n do        begin            for j:=1 to (n+maxn-1)div maxn do            begin                if ans[i,j]<>c[i,j] then  //判断答案是否正确                begin                    p:=true;                    writeln('NO');                    break;                end;            end;            if p then break;        end;        if p then continue;        writeln('YES');    end;end.

不得不说我是时间压线过的

0 0
原创粉丝点击