题解 Codeforce 1478 C. Nezzar and Symmetric Array

题目

题目
题目

题目大意

源自百度翻译:

   很久以前,有一个对称数组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(2
i-1)=0时,a(2i)=0,所以出现重复数字;
当a(2
i-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;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值