对和排序,显然最小是a1+a2,次小a1+a3 然后穷举哪里是a2+a3 这样a1,a2,a3就求出来了
注意a2+a3只可能是前n+1项中的一个,所以穷举这步是O(n)的
接下来我们把已经确定的数的和找到并标记,那么下一个未标记的和就是a1+新的数,然后依次递推下去即可
1 var v:array[0..50010] of boolean; 2 a:array[0..50010] of longint; 3 b:array[0..310] of longint; 4 ans:array[0..10010,0..310] of longint; 5 i,j,n,m,t:longint; 6 7 procedure swap(var a,b:longint); 8 var c:longint; 9 begin 10 c:=a; 11 a:=b; 12 b:=c; 13 end; 14 15 procedure sort(l,r:longint); 16 var i,j,x:longint; 17 begin 18 i:=l; 19 j:=r; 20 x:=a[(l+r) shr 1]; 21 repeat 22 while a[i]<x do inc(i); 23 while x<a[j] do dec(j); 24 if not(i>j) then 25 begin 26 swap(a[i],a[j]); 27 inc(i); 28 dec(j); 29 end; 30 until i>j; 31 if l<j then sort(l,j); 32 if i<r then sort(i,r); 33 end; 34 35 function find(l,r,x:longint):longint; 36 var m:longint; 37 begin 38 while l<=r do 39 begin 40 m:=(l+r) shr 1; 41 if a[m]=x then exit(m); 42 if a[m]>x then r:=m-1 else l:=m+1; 43 end; 44 exit(-1); 45 end; 46 47 procedure check(i:longint); 48 var j,k,p,x,y:longint; 49 begin 50 fillchar(v,sizeof(v),false); 51 fillchar(b,sizeof(b),0); 52 if (a[1]+a[2]-a[i]) mod 2<>0 then exit; 53 b[1]:=(a[1]+a[2]-a[i]) div 2; 54 b[2]:=a[1]-b[1]; 55 b[3]:=a[2]-b[1]; 56 v[1]:=true; v[2]:=true; v[i]:=true; 57 p:=3; 58 for j:=4 to n do 59 begin 60 while (p<=m) and v[p] do inc(p); 61 if p>m then exit; 62 b[j]:=a[p]-b[1]; 63 v[p]:=true; 64 for k:=2 to j-1 do 65 begin 66 if b[k]>=b[j] then exit; 67 x:=find(1,m,b[k]+b[j]); 68 if x=-1 then exit; 69 y:=x; 70 while (y>0) and (a[y]=a[x]) do dec(y); 71 inc(y); 72 while (y<=m) and (a[y]=a[x]) and v[y] do inc(y); 73 if (y>m) or (a[y]<>a[x]) or v[y] then exit; 74 v[y]:=true; 75 end; 76 end; 77 inc(t); 78 ans[t]:=b; 79 end; 80 81 begin 82 readln(n); 83 m:=(n-1)*n div 2; 84 for i:=1 to m do 85 read(a[i]); 86 sort(1,m); 87 for i:=3 to n+1 do 88 if a[i]<>a[i-1] then check(i); 89 writeln(t); 90 for i:=1 to t do 91 begin 92 for j:=1 to n do 93 write(ans[i,j],' '); 94 writeln; 95 end; 96 end.