题目
题目大意
源自百度翻译:
很久以前,有一个对称数组a1,a2,…,a2n由2n个不同的整数组成。数组a1,a2,…,a2n称为对称
的,如果对于每个整数1≤i≤2n,存在一个整数1≤j≤2n,使得ai=−aj。对于每个整数1≤i≤2n,Nezzar写下
一个整数di, 等于ai与a中所有整数的绝对差之和,即di=∑2nj=1 | ai−aj |。现在一百万年过去了,尼扎
尔几乎记不起数组d, 完全忘记了a。尼扎尔想知道是否存在由2n个不同整数组成的对称数组a来生成数组d。
解题思路
首先因为a是一个对称数组,所以2n个不同整数之间必然满足一个数是另一个数的相反数。
其次因为di=∑2nj=1 | ai−aj |,这里我们要先提到一个数学常识:
|a-b|+|a-b|=2max(|a|,|b|);
如:|4-1|+|4+1|=2*4=8;|2-4|+|2+4|=2*4=8;
所以显然 d(i)必定为2的倍数,因此凡是给出的样例中出现d(i)是奇数的情况一律pass;
然后便于观察,我们可以先将d数组从大到小排序一遍,这样如果存在题中所说的a数组必然满足:
d(2*i-1)=d(2*i)(1<=i<=n)且a(2*i-1)=-a(2*i);(假设a(2*i-1)>0,a(2*i)<0)
所以 d1=|a1+a1|+|a1+a2|+|a1+a3|+……+|a1+a2n|=2na1;
d3=|a1+a3|+|a2+a3|+|a3+a3|+……+|a3+a2n|=2a1+(2n-2)a3;
d5=2a1+2a3+(2n-4)a5;
……………………
d2n-1=2a1+2a3+2a5+……+2a(2n-1);
所以我们可以通过计算求出a1,a3,a5……,a2n-1(a2,a4等即为前者相反数)
代码
有两个点昨天被卡了很久,一直wrong
一个是因为题目要求a是2n个不同整数组成,所以样例中得判断有且仅有n对相同的di;
即 不能出现类似 6 6 6 6 的数据;
第二个是因为得保证计算得出的a(2i-1)>0
当a(2i-1)=0时,a(2i)=0,所以出现重复数字;
当a(2i-1)<0时 不满足我们的假设前者为正整数。
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=1e5+50;
long long a[3*maxn];
int cmp(long long a,long long b)
{
return a>b;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
long long n;
scanf("%lld",&n);
int flag=1;//判断是否为奇数
for (int i=1;i<=2*n;i++)
{
scanf("%lld",&a[i]);
if (a[i]%2==1) flag=0;
}
if (!flag)
{
printf("NO\n");
continue;
}
sort(a+1,a+1+2*n,cmp);
int f=1;//判断是否满足所得不重复的正整数
if (a[1]%(2*n)!=0) f=0;
if (!f)
{
printf("NO\n");
continue;
}
long long t=a[1]/(n*2);
for (int i=1;i<=2*n-3;i=i+2)
{
if (a[i]==a[i+2]||(a[i]-a[i+2])%(2*(n-(i+1)/2))!=0||t<=0||a[i]!=a[i+1])
{
f=0;
break;
}
t-=(a[i]-a[i+2])/(2*(n-(i+1)/2));
}
if (a[2*n-1]!=a[2*n]) f=0;
if (t<=0) f=0;
if (!f)
{
printf("NO\n");
continue;
}
else
{
printf("YES\n");
continue;
}
}
return 0;
}