CF2130B题解
CF2130B
赛时感觉这题比CD难,好题。
此题解按照本蒟蒻的赛时思路说,不猜结论。
首先题目要求从\(1\)开始从\(n\)结束,因此至少都要走一遍,先把\(k\)减去\(\sum_{i=1}^{n}a_i\),如果这个时候\(k=0\)那显然无论怎么重排只要往前冲到终点就能攒够;\(k<0\)则无论怎么重排因为至少走一遍都不能刚好凑够\(k\),随意输出排列即可。
对于剩下的\(k\),注意到\(a_i\leq2\),只有三种可选值:\(0\),\(1\),\(2\),且题目保证三个数至少都有一个。考虑对相邻的数讨论:若有相邻的\(0\)和\(1\),显然Alice可以站在这两个上面疯狂刷分,一次刷\(1\)分无论\(k\)是几都能刷到,所以我们必须让\(2\)去隔开\(0\)和\(1\),那我们再分类讨论一下情况:
1.00组合:没贡献,不管了。
2.02组合:显然可以刷够偶数。
3.22组合,无论几个\(2\)去刷肯定是偶数,被情况\(2\)覆盖。
4.21组合,显然可以刷出\(3\)的倍数。
5.11组合,显然可以刷出偶数,被情况2覆盖。
综上所述,我们只需要考虑情况\(2\)和情况\(4\),我们可以列出方程即\(2x+3y=k\),这是个二元丢番图方程,当且仅当\(k\ mod\ gcd(2,3)=0\)才有解,但\(gcd(2,3)=1\),\(k\)是整数所以都能整除,难道无论\(k\)是几都能行吗?不!当\(k=1\)时原方程\(x=-1,y=1\),系数不能出现负数(你不可能拿负数个物品吧),因此\(k≠1\),其他情况均有解。于是这题就做完了。
code
#include <bits/stdc++.h>
//#define int int64_t
//#define int __int128
//#define MOD (1000000007)
//#define eps (1e-6)
#define endl '\n'
#define debug_endl cout<<endl;
#define debug cout<<"debug"<<endl;
using namespace std;
int t,n,s[100],k;
signed main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--){
cin>>n>>k;
int cnt0=0,cnt1=0,cnt2=0;
for(int i=1;i<=n;++i){
cin>>s[i];
if(s[i]==0){
++cnt0;
}
else if(s[i]==1){
++cnt1;
}
else{
++cnt2;
}
k-=s[i];
}
if(k<0){
for(int i=1;i<=n;++i){
cout<<s[i]<<' ';
}
cout<<endl;
continue;
}
if(k==0){
cout<<-1<<endl;
continue;
}
if(k>1){
cout<<-1<<endl;
continue;
}
for(int i=1;i<=cnt0;++i){
cout<<0<<' ';
}
for(int i=1;i<=cnt2;++i){
cout<<2<<' ';
}
for(int i=1;i<=cnt1;++i){
cout<<1<<' ';
}
cout<<endl;
}
return 0;
}

浙公网安备 33010602011771号