C. Sequence Master

发布时间 2023-04-12 16:44:13作者: 模拟退火

题目链接

挺有意思的一道题

题意:给定一个\(2*n\)长度的数组\(p\),要求构造一个长度也为\(2*n\)的整数数组\(q\),使得\(q\)满足从\(q\)中任选\(n\)个数字的积等于\(q\)中剩下\(n\)个数的和,求出\(p\)\(q\)的最短距离

最短距离定义为对应元素差的绝对值之和

由于\(q\)的要求有点严苛,先考虑如何构造\(q\)(条件严格的话\(q\)的数量可能很小,因此后面算最小距离时可能可以暴力枚举)

分为两种情况考虑:

\(\forall i,j\)\(q_i==q_j\)

因为其强对称性考虑全部元素都相等,此时有\(q_i^n==n*q_i\)

·得到一组通解\(q_i=0\)

·以及当\(n==1\)时,\(q_i\)可以为任意值

·当\(n==2\)时,\(q_i==2\)

\(q_i\)不全相等时,不妨设有\(q_1!=q_2\)

此时有方程组:

\(\begin{cases}q_1*q_3*q_4*\cdots*q_{n+1}=q_2+q_{n+2}+\cdots+q_{2n}\\q_2*q_3*q_4*\cdots*q_{n+1}=q_1+q_{n+2}+\cdots+q_{2n}\end{cases}\)

两式相减得: \((q_1-q_2)*q_3*q_4*\cdots*q_{n+1}=q_2-q_1\)

即: \((q_1-q_2)*(q_3*q_4*\cdots*q_{n+1}+1)=0\)

由于\(q_1!=q_2\),所以\(q_3*q_4*\cdots*q_{n+1}=-1\)

因为\(q\)的限制是任意\(n\)个数,所以其实\(q_{3,\cdots,2n}\)这些数中任意取\(n-1\)个的乘积都为\(-1\)

又因为\(q_i\)为整数,所以只有当\(2|n\)时,才有解:\(q_3=q_4=\cdots=q_2n=-1\)

代回方程得:\(q_1*(-1)=q_2-n+1\)

即:\(q_1+q_2=n-1\)

又有:\(q_1*q_2*\cdots*q_n=q_{n+1}+\cdots+q_{2n}\)

即:\(q_1*q_2=-n\)

解得 \(q_1=n,q_2=-1\),无论顺序

综上,由于只有三种情况,暴力讨论距离最小值即可

点击查看代码
#include<bits/stdc++.h>
#include<vector>
#include<map>
#include<queue>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 300007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
inline int Read()
{
	char ch=getchar();bool f=0;int x=0;
	for(;!isdigit(ch);ch=getchar())if(ch=='-')f=1;
	for(;isdigit(ch);ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
	if(f==1)x=-x;return x;
}
int T=1,n,m;
bool Solve()
{
 	//freopen("test.in","r",stdin);
	n=Read();
	vector<int> a;
	for(int i=1;i<=2*n;++i)
	{
		int in=Read();
		a.emplace_back(in);
	}
	if(n==1)
	{
		printf("%lld\n",abs(a[1]-a[0]));
		return 1;
	}
	sort(a.begin(),a.end());
	int s1=0,s2=0,s3=0;
	for(int i=0;i<a.size();++i)
	{
		s1+=abs(a[i]);
		s2+=abs(a[i]-2);
		if(i+1!=a.size())
			s3+=abs(a[i]+1);
	}
	s3+=abs(a[a.size()-1]-n);
	if(n==2)
	{
		printf("%lld\n",min(s1,min(s2,s3)));
		return 1;
	}
	if(n%2==0)
		printf("%lld\n",min(s1,s3));
	else
		printf("%lld\n",s1);
	return true;
}
signed main()
{
	T=Read();
	while(T--)
		if(!Solve())
			printf("-1\n");
	return 0;
}
/*
-std=c++11
-std=c99
*/