CSP2026多校联考Day3 C-混乱邪恶

image
先给出官方题解:
image
第一眼:写的什么玩意?
题解并没有给出构造方法,只有证明。
转换题意,即从这一堆数中选出来一些,使选出来数的和为所有数和一半。
于是我尝试借鉴倍增的思想,即任何数都可以拆成多个二的不同次幂的和,
将原数组备份,并按降序排序排序,即这些数的和的一半为 \(s\),依次尝试每一个数,如果这个数小于 \(s\) 就将其填入,并将 \(s\) 减去这个数的值,直到 \(s\) 为零,就构造出了一个合法方案。
但这个假了,这终究不是倍增,所以需要在此基础上写一个搜索:

96' code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int NUM=1e6+10;

int n,m;
int a[NUM],b[NUM];
int sum;
int vis[NUM];

bool dfs(int x,int s){
	if(s<0) return 0;
	if(s==0) return 1;
	for(int i=x;i<=n;++i){
		vis[b[i]]++;
		if(dfs(i+1,s-b[i])) return 1;
		vis[b[i]]--;
	}
	return 0;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>a[i];sum+=a[i];b[i]=a[i];
	}
	sum/=2;
	sort(b+1,b+1+n,[](int x,int y){
		return x>y;
	});
	if(dfs(1,sum)){
		cout<<"NP-Hard solved\n";
		for(int i=1;i<=n;++i){
			if(vis[a[i]]){
				cout<<1<<' ';vis[a[i]]--;
			}
			else cout<<-1<<' ';
		}
	}else cout<<"Chaotic evil\n";
//	cout<<dfs(1,sum)<<'\n';
		
	return 0;
}

他T了。
于是我们考虑再看一眼题解:
题解构造了一个 \(d\) 数组,于是我受此启发,不是直接求 \(c\),而是求 \(e\) 来反推 \(c\)
因为 \(d_i=b_{i\times 2 -1}-b_{i\times 2}\) (在我这里是这样的),所以当 \(e_i=1\)\(b_{i\times 2 -1}\) 对应的 \(c_{b_{i\times 2 -1}}\) 的值为 \(1\)\(c_{b_{i\times 2}}\)\(-1\)
时间复杂度约为 \(O(kn)\),其中 \(k\) 是一个较小的常数,在特殊构造的题目还是会退化的。

100' code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int NUM=1e6+10;

int n,m;
int a[NUM],b[NUM],d[NUM];
int sum;
bool vis[NUM];

bool dfs(int x,int s){
	if(s<0) return 0;
	if(s==0) return 1;
	for(int i=x;i<=(n+1)/2;++i){
		vis[b[i*2-1]]^=1;vis[b[i*2]]^=1;
		if(dfs(i+1,s-d[i])) return 1;
		vis[b[i*2-1]]^=1;vis[b[i*2]]^=1;
	}
	return 0;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		cin>>a[i];b[i]=a[i];
	}
	sort(b+1,b+1+n,[](int x,int y){
		return x>y;
	});
	for(int i=1;i<=(n+1)/2;++i){
		d[i]=b[i*2-1]-b[i*2];
		vis[b[i*2-1]]=1;
		sum+=d[i];
	}
	sum/=2;
	if(dfs(1,sum)){
		cout<<"NP-Hard solved\n";
		for(int i=1;i<=n;++i){
			if(vis[a[i]]){
				cout<<1<<' ';
			}
			else cout<<-1<<' ';
		}
	}else cout<<"Chaotic evil\n";
		
	return 0;
}
posted @ 2026-07-15 08:43  LZYXT  阅读(15)  评论(1)    收藏  举报