题解:CF2130B Pathless

· · 题解

题意

# 思路 我们可以在输入时便记录 $\sum^n_{i=1}a_i$ 以及 $0$,$1$,$2$ 的个数,然后令 $op=s-\sum^n_{i=1}a_i$。当 $op=1$ 或 $op<0$ 时,我们就可以先输出完所有的 $0$,再输出完所有的 $2$,最后输出剩下的 $1$;否则直接输出 $-1$。 # 证明 已知 $op=s-\sum^n_{i=1}a_i$,令 $sum=\sum^m_{j=1}a_{i_j}$,那么这里我们分 $3$ 种情况进行讨论: - $op<0$:说明哪怕我全程只走一次都会导致 $sum>s$,如果我还来回走显然 $op$ 会更小,因此在该情况下任意排列均正确。 - $op=1$:说明 $s=sum+1$,那么我全程只要有一个 $1$ 和 $0$ 相邻,来回走一下,就会使 $sum+1\to sum=s$,因此,我们就要让 $0$ 和 $1$ 分隔开,故先输出所有的 $0$,再输出所有的 $2$,最后输出所有的 $1$ 即可使得无论如何都满足 $sum\ne s$。 - $op=0$ 或 $op>1$:那么此时无论我怎么进行排列,总会有 $0$,$1$,$2$ 之间存在相邻,那么进而我就可以得到 $2$,$3$,$5$,然后就可以通过任意个 $2$,$3$,$5$ 的组合得到任意大于等于 $2$ 的数,显然就无解了,此时输出 $-1$ 即可。 综上所述,当 $op<0$ 或 $op=1$ 时,我们可以通过先输出所有的 $0$,再输出所有的 $2$,最后输出所有的 $1$ 即为正确答案,而当 $op=0$ 或 $op>1$ 时,直接输出 $-1$ 即可,证毕。 # Code ```cpp #include<bits/stdc++.h> #define endl "\n" #define ll long long #define N 1006 using namespace std; int t,n,s,a[N],sum; int mp[N];//mp记录0,1,2的个数 inline int read(); int main(){ t=read(); while(t--){ memset(mp,0,sizeof(mp));//多测不清空,亲人两行泪 sum=0; n=read();s=read(); for(int i=1;i<=n;i++) a[i]=read(),mp[a[i]]++,sum+=a[i]; s-=sum; if(s==1 || s<0){ for(int i=1;i<=mp[0];i++) cout<<0<<" "; for(int i=1;i<=mp[2];i++) cout<<2<<" "; for(int i=1;i<=mp[1];i++) cout<<1<<" "; cout<<endl; }else cout<<-1<<endl; } return 0; } inline int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {x=x*10+ch-48;ch=getchar();} return x*f; } ```