1 条题解
-
0
思路
将 从小到大排序,考虑从小到大确定 。注意到若确定了 ,则一定可以确定 ,因为记可重集 $S_i = \{s_1,\dots,s_n\} \setminus \{a_j + a_k \mid 1 \leq j < k \leq i\}$,显然有 。
那么若能确定 的取值,就能还原出整个 序列。不难发现 ,此时若能找到一个 满足 就能直接得到 的取值。因为只有 有可能 ,因此满足条件的 一定有 ,不妨直接枚举 的值。
实现上可以用一个 multiset 时刻维护 ,复杂度 ,可能需要卡常才能过。由于每次只需要求 ,并且一定有 ,所以可以直接用一个桶维护这个元素是否还在集合中,再用一个指针扫,能做到 。
Code
#include <bits/stdc++.h> #define re register using namespace std; const int N = 310,M = N * N; int n,m; int arr[M],p[N]; vector<vector<int>> ans; inline int read(){ int r = 0,w = 1; char c = getchar(); while (c < '0' || c > '9'){ if (c == '-') w = -1; c = getchar(); } while (c >= '0' && c <= '9'){ r = (r << 3) + (r << 1) + (c ^ 48); c = getchar(); } return r * w; } int main(){ n = read(),m = n * (n - 1) / 2; for (re int i = 1;i <= m;i++) arr[i] = read(); sort(arr + 1,arr + m + 1); for (re int i = 3;i <= n;i++){ if (i > 3 && arr[i] == arr[i - 1]) continue; if ((arr[1] + arr[2] + arr[i]) & 1) continue; unordered_map<int,int> mp; for (re int j = 1;j <= m;j++) mp[arr[j]]++; p[1] = (arr[1] + arr[2] + arr[i]) / 2 - arr[i]; p[2] = (arr[1] + arr[2] + arr[i]) / 2 - arr[2]; p[3] = (arr[1] + arr[2] + arr[i]) / 2 - arr[1]; if (!p[1]) continue; mp[p[1] + p[2]]--,mp[p[1] + p[3]]--,mp[p[2] + p[3]]--; for (re int j = 4,id = 1;j <= n;j++){ while (id <= m && !mp[arr[id]]) id++; p[j] = arr[id] - p[1]; for (re int k = 1;k < j;k++){ int x = p[j] + p[k]; if (!mp.count(x) || !mp[x]) goto End; else mp[x]--; } } ans.push_back(vector<int>{}); for (re int j = 1;j <= n;j++) ans.back().push_back(p[j]); End:; } printf("%d\n",ans.size()); for (vector<int> v:ans){ for (int x:v) printf("%d ",x); puts(""); } return 0; }
- 1
信息
- ID
- 4462
- 时间
- 19000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者