bzoj2797

时间:2024-07-11 15:06:56

对和排序,显然最小是a1+a2,次小a1+a3 然后穷举哪里是a2+a3 这样a1,a2,a3就求出来了

注意a2+a3只可能是前n+1项中的一个,所以穷举这步是O(n)的

接下来我们把已经确定的数的和找到并标记,那么下一个未标记的和就是a1+新的数,然后依次递推下去即可

 var v:array[..] of boolean;
a:array[..] of longint;
b:array[..] of longint;
ans:array[..,..] of longint;
i,j,n,m,t:longint; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ];
repeat
while a[i]<x do inc(i);
while x<a[j] do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; function find(l,r,x:longint):longint;
var m:longint;
begin
while l<=r do
begin
m:=(l+r) shr ;
if a[m]=x then exit(m);
if a[m]>x then r:=m- else l:=m+;
end;
exit(-);
end; procedure check(i:longint);
var j,k,p,x,y:longint;
begin
fillchar(v,sizeof(v),false);
fillchar(b,sizeof(b),);
if (a[]+a[]-a[i]) mod <> then exit;
b[]:=(a[]+a[]-a[i]) div ;
b[]:=a[]-b[];
b[]:=a[]-b[];
v[]:=true; v[]:=true; v[i]:=true;
p:=;
for j:= to n do
begin
while (p<=m) and v[p] do inc(p);
if p>m then exit;
b[j]:=a[p]-b[];
v[p]:=true;
for k:= to j- do
begin
if b[k]>=b[j] then exit;
x:=find(,m,b[k]+b[j]);
if x=- then exit;
y:=x;
while (y>) and (a[y]=a[x]) do dec(y);
inc(y);
while (y<=m) and (a[y]=a[x]) and v[y] do inc(y);
if (y>m) or (a[y]<>a[x]) or v[y] then exit;
v[y]:=true;
end;
end;
inc(t);
ans[t]:=b;
end; begin
readln(n);
m:=(n-)*n div ;
for i:= to m do
read(a[i]);
sort(,m);
for i:= to n+ do
if a[i]<>a[i-] then check(i);
writeln(t);
for i:= to t do
begin
for j:= to n do
write(ans[i,j],' ');
writeln;
end;
end.