社区讨论
还能接着卡吗
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 里面一长串是把这个狗题拆成了枚举子集。#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 条回复,欢迎继续交流。
正在加载回复...