CF1599J题解
以下称题目中给出的序列为“原序列”。
首先有一个显而易见的结论,若原序列存在相同的数,那么直接可以得出:相同的数其中一个变成
我们发现,对于原序列
对于一个长度为
这就有两种可能:均为偶数或者二奇一偶。
当原序列中存在偶数时:
否则,我们现在的序列中全部是奇数。
这时我们尝试去寻找一个可能的子序列,长度为奇数的子序列不可能成为目标,因为类似上面长度为
于是我们假设有一个长度为
需要满足
也就是说我们需要在原序列中找出任意两个不完全相同的集合,满足大小和元素和均相等(若有重复元素就同时删去)。
我们发现,对于大小为
可以用哈希表来实现。
using namespace std;
# include<bits/stdc++.h>
# include<bits/extc++.h>
int N;
constexpr int maxn(1002);
int a[maxn];
void work1(){
if(N==2){
if(a[1]==a[2]){
printf("YES\n0 %d\n",a[1]);
return;
}else{
printf("NO\n");
return;
}
}
if(N==3){
if(a[1]==a[2]){
printf("YES\n0 %d %d\n",a[2],a[3]);
return;
}else if(a[2]==a[3]){
printf("YES\n0 %d %d\n",a[1],a[3]);
return;
}
}
std::vector<int>o,j;
for(int i=1;i<=N;i++) if(a[i]%2==0) o.push_back(i);else j.push_back(i);
if(N==3&&j.size()<2){
puts("NO");
return;
}
int A,B,C;
if(o.size()>=3){
A=o[0],B=o[1],C=o[2];
}else A=o[0],B=j[0],C=j[1];
int X=(a[A]-a[B]+a[C])>>1;
puts("YES");
printf("%d %d %d ",X,a[A]-X,a[B]-a[A]+X);
for(int i=1;i<=N;i++){
if(i==A||i==B||i==C) continue;
printf("%d ",a[i]-X);
}
}
struct aqua{
std::vector<int>v;
aqua(){};
aqua(std::vector<int>t){v=t;}
};
void print(std::vector<int>A,std::vector<int>B){
static bool visa[maxn],visb[maxn];
for(auto x:A) visa[x]=1;
for(auto x:B) visb[x]=1;
A.clear(),B.clear();
for(int i=1;i<=N;i++){
if(visa[i]^visb[i]){
if(visa[i]) A.push_back(i);
else B.push_back(i);
}
}
int X=0;
puts("YES");
for(int i=0;i<A.size();i++){
printf("%d ",X);
X=a[A[i]]-X;
printf("%d ",X);
X=a[B[i]]-X;
}
for(int i=1;i<=N;i++){
if(visa[i]^visb[i]) continue;
printf("%d ",a[i]);
}
}
void work2(){
__gnu_pbds::gp_hash_table<int,int>h[30];
for(int i=1;i<1<<N;i++){
int g=__builtin_popcount(i);
int s=0;
for(int j=1;j<=N;j++){
if((i>>(j-1))&1) s+=a[j];
}
if(h[g][s]){
int x=i,y=h[g][s];
std::vector<int>a,b;
for(int j=1;j<=N;j++){
if((x>>(j-1))&1) a.push_back(j);
if((y>>(j-1))&1) b.push_back(j);
}
print(a,b);
return;
}
h[g][s]=i;
}
puts("NO");
}
std::vector<int>xl;
__gnu_pbds::gp_hash_table<int,aqua>hs;
void dfs(int d,int now,int z){
if(d==28){
if(!hs[z].v.empty()){
print(hs[z].v,xl);
exit(0);
}
hs[z]=aqua(xl);
return;
}
for(int i=now;i<=N;i++)
xl[d]=i,dfs(d+1,i+1,z+a[i]);
}
void work3(){
xl.resize(28);
dfs(0,1,0);
puts("NO");
}
int main(){
std::cin>>N;
bool fg=0;
for(int i=1;i<=N;i++) scanf("%d",&a[i]),fg|=a[i]%2==0;
std::sort(a+1,a+N+1);
if(fg){
work1();
return 0;
}
if(N<=28) work2();
else work3();
return 0;
}