社区讨论

还能接着卡吗

P9234[蓝桥杯 2023 省 A] 买瓜参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mjjrhjca
此快照首次捕获于
2025/12/24 16:38
2 个月前
此快照最后确认于
2025/12/26 21:05
2 个月前
查看原帖
不想写剪枝,遂换了好几种哈希方式,并使用开放寻址拿了 92 pts。record
瓶颈在于空间限制 /fn,有没有什么卡常技巧 qwq。
main 里面一长串是把这个狗题拆成了枚举子集。
CPP
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
constexpr uint mod=52000009;

int n,m;
uint s[35];

uint cnt[1<<15];

int x,y;
uint a[15],b[15];
uint sa[1<<15],sb[1<<15];

uint key[mod];
char val[mod];

void insert(uint K,char V){
	for(uint p=(K%mod);;p=(p+1)%mod){
		if(key[p]==K){
			val[p]=min(val[p],V);
			return;
		}
		if(key[p]==-1){
			key[p]=K,val[p]=V;
			return;
		}
	}
}

char query(uint K){
	for(uint p=(K%mod);;p=(p+1)%mod){
		if(key[p]==K) return val[p];
		if(key[p]==-1) return 100;
	}
}

uint ans=1e9;

int main(){
	ios::sync_with_stdio(0);
	
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>s[i];
	
	m*=2;
	x=n/2,y=n-x;
	
	for(int i=1;i<=n;++i){
		if(i<=n/2) a[i-1]=s[i];
		else b[i-n/2-1]=s[i];
	}
	
	for(int i=1;i<(1<<15);++i){
		for(int j=0;j<15;++j){
			if(i&(1<<j)) ++cnt[i];
		}
	}
	
	for(int i=1;i<(1<<x);++i){
		for(int j=0;j<x;++j){
			if(i&(1<<j)) sa[i]+=a[j];
		}
	}
	
	for(int i=1;i<(1<<y);++i){
		for(int j=0;j<y;++j){
			if(i&(1<<j)) sb[i]+=b[j];
		}
	}
	
	memset(key,-1,sizeof(key));
	
	insert(0,0);
	
	for(int i=1;i<(1<<x);++i){
		for(int j=i;j;j=(j-1)&i){
			uint k=sa[i]+sa[j],v=cnt[i]-cnt[j];
			if(k>m) continue;
			if(k==m) ans=min(ans,v);
			else insert(k,v);
		}
		uint k=sa[i],v=cnt[i];
		if(k>m) continue;
		if(k==m) ans=min(ans,v);
		else insert(k,v);
	}
	
	for(int i=1;i<(1<<y);++i){
		for(int j=i;j;j=(j-1)&i){
			uint k=sb[i]+sb[j],v=cnt[i]-cnt[j];
			if(k<=m) ans=min(ans,query(m-k)+v);
		}
		uint k=sb[i],v=cnt[i];
		if(k<=m) ans=min(ans,query(m-k)+v);
	}
	
	if(ans>50) cout<<-1<<endl;
	else cout<<ans<<endl;
	
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...