Nezzar and Symmetric Array
题意
有 2 n 2n 2n 个不同的整数 对于每个 1 ≤ i ≤ 2 n 1\leq i \leq 2n 1≤i≤2n 都存在 1 ≤ j ≤ 2 n 1\leq j \leq 2n 1≤j≤2n 使得 a i = − a j a_i = -a_j ai=−aj
d i = ∑ j = 1 2 n ∣ a i − a j ∣ d_i = \sum_{j = 1}^{2n}{|a_i - a_j|} di=∑j=12n∣ai−aj∣ 给你 d d d 问是否存在符合条件的原数组
思路
举个例子 − 4 , − 3 , − 2 , − 1 , 1 , 2 , 3 , 4 -4 ,-3,-2,-1,1,2,3,4 −4,−3,−2,−1,1,2,3,4 可以发现规律 :一个数到一个较小的数和这个较小的数的相反数的距离是自身的两倍 比如 4 到 -3 和 4 到 3 距离为 8
并且一个绝对值较小的数和两个绝对值比它大的正负数的距离和 = 二倍大数的绝对值
所以可以从大到小考虑依次还原数组 判断是否符合条件即可 又发现了一个规律
首先记录 d d d数组中每个数出现的次数 稍微想一下可以知道 一个数肯定是两个两个出现 并且是偶数
用 s u m sum sum 记录 当前数到比它绝对值大的数的距离 t . f i r s t t.first t.first 减去 s u m sum sum 后得到的为 当前数到所有绝对值小于等于自己的数(这样的数有n个 每次找到后 n–)的距离 可以得到 x x x = ( t . f i r s t − s u m ) / 2 / n = (t.first - sum) / \ 2 \ / \ n =(t.first−sum)/ 2 / n
记录上一个找到的数为 l a s las las 因为是从大到小找且找正的那个 所以 如果 x > = l a s ∣ ∣ x < = 0 x >= las \ \ || \ \ x <= 0 x>=las ∣∣ x<=0 就不合题意了
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
//#define mod 1000000007
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;
inline LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
const int N = 200010;
int n;
LL a[N];
bool cmp(LL a, LL b) {
return a > b;
}
void solve() {
bool flag = true;
cin >> n;
map<LL, LL, greater<LL>>mp;
for (int i = 1; i <= 2 * n; ++i) {
cin >> a[i];
mp[a[i]]++;
}
LL las = LLONG_MAX;
LL sum = 0;
for (auto &t : mp) {
//cout << "t.first == " << t.first << endl;
if (t.second != 2) {
flag = false;
break;
}
else if (t.first & 1) {
flag = false;
break;
}
else {
if (((t.first - sum) / 2) % n) {
flag = false;
break;
}
LL x = (t.first - sum)/ 2 / n;
//cout << "x == " << x << endl;
if (x <= 0 || x >= las) {
flag = false;
break;
}
n--;
sum += 2 * x;
las = x;
}
}
if (flag)puts("YES");
else puts("NO");
}
int main() {
int t; cin >> t;
while (t--)
solve();
return 0;
}