{题解}[jzoj1021]【中山市选2008】矩阵

jzoj1021

Description
给出A,B,C三个01矩阵,问A*B是否等于C.
Input
本题有多组数据.
第一行的ca表示一共有ca组数据.
对于每组数据,第一行有一个整数N(1<=N<=1000)
然后就是A,B,C三个矩阵.
Output
对于每组数据,输出一行.
如果A*B=C,就输出“YES”,否则输出“NO”。

不要被矩阵乘法吓到了。
只要理解矩阵乘法就足矣

Ci,j=k=1nAi,kBk,j

二进制的话,将 乘法改为 And加法改为 Xor即可。
我们还是需要一个性质: 矩阵乘法满足交换律
于是乎,我们可以引入一个 友矩阵(大小为1*n)
之后
AB=CABF=CF

不过这个 友矩阵怎么计算呢?
全为0是有问题的,全为1也是有问题的!(可以伸出脚趾算一算)
怎么办呢?机(yi)智(ban)的,可以运用 random这个少见的小东西。
多次进行判断即可Ac。(请洗脸)

如果无聊,可以参考一下Infleaking的分治(高精度原理)
Code
正解

        maxt=5;
        maxn=100000;
var
        t,n:longint;
        i,j,l:longint;
        x,y,z,f:array[0..maxn] of longint;
        a,b,c:array[0..maxn,0..maxn] of longint;
procedure init;
var
        ch:char;
        i,j,l:longint;
begin
        readln(n);
        for i:=1 to n do
        begin
                for j:=1 to n do
                begin
                        read(ch);
                        if(ch='0')then a[i,j]:=0 else a[i,j]:=1;
                end;
                readln;
        end;
        for i:=1 to n do
        begin
                for j:=1 to n do
                begin
                        read(ch);
                        if(ch='0')then b[i,j]:=0 else b[i,j]:=1;
                end;
                readln;
        end;
        for i:=1 to n do
        begin
                for j:=1 to n do
                begin
                        read(ch);
                        if(ch='0')then c[i,j]:=0 else c[i,j]:=1;
                end;
                readln;
        end;
end;
procedure randomf;
var
        i:longint;
begin

        for i:=1 to n do f[i]:=random(2);
        fillchar(x,sizeof(x),0);
        fillchar(y,sizeof(y),0);
        fillchar(z,sizeof(z),0);
end;
procedure work;
var
        i,j,l:longint;
begin
        for i:=1 to 5 do
        begin
                randomf;
                for j:=1 to n do
                for l:=1 to n do
                y[j]:=y[j] xor (b[j,l] and f[l]);

                for j:=1 to n do
                for l:=1 to n do
                x[j]:=x[j] xor (a[j,l] and y[l]);

                for j:=1 to n do
                for l:=1 to n do
                z[j]:=z[j] xor (c[j,l] and f[l]);

                for j:=1 to n do
                if(x[j]<>z[j])then
                begin
                        writeln('NO');
                        exit;
                end;
        end;
        writeln('YES');
end;
begin
        randomize;
        readln(t);
        while t>0 do
        begin
                dec(t);
                init;
                work;
        end;
end.

Infleaking分块

const
        mo=60;
type
        col=array[0..18]of int64;
var
        i,j,k,m,n,x,y,z,q,ca:longint;
        f:int64;
        b,c:array[1..1000]of col;
        a:array[1..1000,1..1000]of longint;
        m2:array[0..60]of int64;
        x1,y1,z1:col;
        p:boolean;
        e:char;
function mul(a,b:col):col;
var
        i:longint;
begin
        for i:=0 to 18 do
        mul[i]:=a[i] and b[i];
end;
function add(a,b:col):col;
var
        i:longint;
begin
        for i:=0 to 18 do
        add[i]:=a[i] xor b[i];
end;
function xd(a,b:col):boolean;
var
        i:longint;
begin
        for i:=0 to 18 do if a[i]<>b[i] then exit(false);
        exit(true);
end;
begin
        m2[0]:=1;
        for i:=1 to 60 do m2[i]:=m2[i-1]*2;
        read(ca);
        for q:=1 to ca do
        begin
                readln(n);
                fillchar(a,sizeof(a),0);
                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(e);
                                if e='1' then

                                a[i,j]:=1;
                        end;
                        readln;
                end;
                for i:=1 to n do
                begin
                        for j:=1 to n do
                        begin
                                read(e);
                                f:=n-j;
                                if e='1' then
                                b[i][(j-1) div mo+1]:=b[i][(j-1) div mo+1]+m2[f mod mo];
                        end;
                        readln;
                end;
                for i:=1 to n do
                begin
                        for j:=1 to n do
                        begin
                                read(e);
                                f:=n-j;
                                if e='1' then
                                c[i][(j-1) div mo+1]:=c[i][(j-1) div mo+1]+m2[f mod mo];

                        end;
                        readln;
                end;
                p:=true;
                for i:=1 to n do
                begin
                        fillchar(x1,sizeof(x1),0);
                        for j:=1 to n do
                        begin
                                if a[i,j]=1 then
                                x1:=add(x1,b[j]);
                        end;
                        if not xd(x1,c[i]) then
                        begin
                                p:=false;
                                writeln('NO');
                                break;
                        end;
                end;
                if p then writeln('YES');
        end;
end.

你可能感兴趣的:({题解}[jzoj1021]【中山市选2008】矩阵)