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;
}
posted @ 2025-08-01 09:57  司马只因锥  阅读(13)  评论(0)    收藏  举报