5/1/周赛/E/都市题解
原题链接
可以先将原数组排序。
设答案数列为 \(a_1,a_2,...,a_n (a_i\leq a_{i+1}\ \ \ i\in [1,n-1])\) , 原数组为 \(b\)。
我们发现,\(b_1\) 的一定是 \(a_1 + a_2\),\(b_2\) 的一定是 \(a_2 + a_3\)。
但是,到了 \(b_3\) 有可能是 \(a_1+a_4\) 或 \(a_2+a_3\)。
所以我们要枚举 \(a_2 + a_3\) 是 \(b_?\ \ ?\in[3,n+1]\)。
到 \(n\) 结束是因为最多 \(a_2+a_3 \geq a_1+a_n\) \(a_1+a_n\) 下一个就一定是 \(a_2+a_3\)。
设枚举 \(a_2 + a_3 = b_x\),那么我们可以求出 \(a_1,a_2,a_3\)。
从 \(b_3 \sim b_x\) 为 \(a_1+a_i\)。
所以可以求出 \(a_1 \sim a_x\)。
接下来我们删去 \(b\) 中 \(a_1 \sim a_x\) 中两两组合的和,接着对于剩下的 \(b_1\) 肯定是 \(a_1+a_x\) 求出 \(x\) 后再次删去 \(b\) 中 \(a_1 \sim a_x\) 中两两组合的和,以此类推。
最后输出即可。
#include<bits/stdc++.h>
using namespace std;
int a[100010];
int b[100010];
set<vector<int>> da;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
multiset<int> s;
for(int i=1;i<=n*(n-1)/2;i++)
{
cin>>a[i];
s.insert(a[i]);
}
if(n == 2)
{
cout<<a[1]/2<<'\n';
for(int i=a[1]/2;i>=1;i--)
{
cout<<i<<' '<<a[1]-i<<'\n';
}
return 0;
}
if(n == 3)
{
sort(a+1,a+1+n*(n-1)/2);
b[1]=(a[1]+a[2]+a[3])/2-a[3];
b[2]=(a[1]+a[2]+a[3])/2-a[2];
b[3]=(a[1]+a[2]+a[3])/2-a[1];
s.erase(s.find(a[1]));
s.erase(s.find(a[2]));
s.erase(s.find(a[3]));
for(int i=4;i<=n;i++)
{
b[i]=*s.begin()-b[1];
for(int j=1;j<i;j++)
{
if(s.find(b[i]+b[j])!=s.end())
{
s.erase(s.find(b[i]+b[j]));
}
}
}
vector<int> v;
for(int i=1;i<=n;i++)
{
v.push_back(b[i]);
}
sort(v.begin(),v.end());
cout<<1<<'\n';
for(auto it:v)
{
cout<<it<<' ';
}
cout<<'\n';
return 0;
}
sort(a+1,a+1+n*(n-1)/2);
for(int step=3;step<=n;step++)
{
vector<int> v;
if((a[1]+a[2]+a[step])%2!=0)
{
goto it;
}
b[1]=(a[1]+a[2]+a[step])/2-a[step];
b[2]=(a[1]+a[2]+a[step])/2-a[2];
b[3]=(a[1]+a[2]+a[step])/2-a[1];
s.clear();
for(int i=1;i<=n*(n-1)/2;i++)
{
s.insert(a[i]);
}
for(int i=4;i<=step;i++)//求值
{
b[i]=a[i-1]-b[1];
}
for(int i=1;i<=step;i++)
{
for(int j=i+1;j<=step;j++)
{
if(s.find(b[i]+b[j]) == s.end())//删除时顺便判断一下
{
goto it;
}
else
{
s.erase(s.find(b[i]+b[j]));
}
}
}
for(int i=step+1;i<=n;i++)
{
b[i]=*s.begin()-b[1];//求值
for(int j=1;j<i;j++)
{
if(s.find(b[i]+b[j]) == s.end())//删除时顺便判断一下
{
goto it;
}
else
{
s.erase(s.find(b[i]+b[j]));
}
}
}
for(int i=1;i<=n;i++)
{
if(b[i]<1||b[i]<b[i-1])//最后判断是否合法
{
goto it;
}
}
for(int i=1;i<=n;i++)
{
v.push_back(b[i]);
}
da.insert(v);//记录答案+排序+去重
it: ;
}
cout<<da.size()<<'\n';
for(auto it=da.rbegin();it!=da.rend();it++)//输出
{
for(auto it1:*it)
{
cout<<it1<<' ';
}
cout<<'\n';
}
return 0;
}
作者:
ltl0825
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号