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;
}
posted @ 2025-05-02 11:14  ltl0825  阅读(8)  评论(0)    收藏  举报