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”。
不要被矩阵乘法吓到了。
只要理解矩阵乘法就足矣
random
这个少见的小东西。
如果无聊,可以参考一下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.