思路:
因为这个对称性得特性,并且2n个数字是不一样得,那么我们就能从这里入手,按照绝对值来讲,a[i] = -a[j]得话,那么d[i] = d[j],并且a数组里面不能有0,因为有零就需要另一个零和他配对,成为对称数组。
那么,给出来得d数组就能够有了一个限制:得到得每一个数字有且仅有两个。(因为上面得d[i]=d[j])。
这个j是没有位置限制得,那么我们就把a数组从小到大排序,只要求出来正得那一半得a[i](1<=i<=n)那么就说明是可以得到a数组得,就输出yes。
说完yes了,那么有没有可能又出现No得可能呢。答案是当然得,因为这个a有可能是求不到的。既然这样,那么就需要知道如何求出来每一个a[i]了(正得)。
从小到大对啊a[i]进行排序(假设a存在),a[1]、a[2]、……a[n] …… -a[1]……-a[n],那么,我们来推断a得通式吧!
d[i] = (a[i]-a[1] + a[i] - a[2] + …… +a[i] - a[i] + a[i+1]-a[i] + a[i+2] - a[i]+ …… +a[n] - a[i])+(a[i]+a[1] + a[i]+a[2]+……+a[i]+a[n])
d[i] = (i*a[i]-si+sn-si-(n-i)*a[i]) +(n*a[i]+sn) = 2*(i*a[i]-si+sn),这样子a[i]就有了,a[i] = d[i]-2*(sn-si)/2*i,那么这个sn-si怎么求呢,那么很特殊得a[n]=d[n]/2*i,那么s[n]-s[i]不是手到擒来了。(sn表示a1+……+an)。
那么从后向前求a[i]就可以啦,如果a[i]求出来是分数,那么这个a是不存在,这就是d得另一个限制
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve(){
int n;
cin >> n;
int a[2*n+2];
int flag = 0;
for(int i = 1;i <= 2 * n; i++) {
cin >> a[i];
if(a[i] & 1){
flag = 1;//其实是第二个限制
}
}
sort(a+1,a+2*n+1);
int b=a[1];
int cnt = 0;//第一个限制
for(int i = 1;i<=2*n;i++){
if(a[i]==b){
cnt++;
}
else{
if(cnt !=2){
cout << "NO\n";
return ;
}
cnt=1;
b=a[i];
}
}
if(cnt != 2) {
cout << "No\n";
return ;
}
vector<int> d;
for(int i = 1;i<=2*n;i+=2){
d.push_back(a[i]);
}
sort(d.begin(),d.end());
if(flag){
cout << "NO\n";
return ;
}
int sum[n+2]={0};
for(int i = n-1;i >=0;i --){//第二个限制
if((d[i]-2*sum[i+1])<=0) {
cout << "NO\n";
return ;
}
if((d[i]-2*sum[i+1])%(2*(i+1))) {
cout << "NO\n";
return ;
}
sum[i]=sum[i+1]+(d[i]-2*sum[i+1])/(2*(i+1));//这个就是s[n]-s[i]因为是从后向前面求,所以是sum[i+1]+a[i],后面一大堆是a[i]。
}
cout << "YES\n";//两道限制都过了,直接yes
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
solve();
}
return 0;
}