专栏文章
题解:P12878 [蓝桥杯 2025 国 C] 拔河
P12878题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mip1eux2
- 此快照首次捕获于
- 2025/12/03 04:35 3 个月前
- 此快照最后确认于
- 2025/12/03 04:35 3 个月前
P12878 题解:
好题。
主要思路:
看到题目第一眼就想到了背包,但值域太大,不太行。于是又想到把 个数分成 组,每组 个数,采用 Meet-in-the-middle 算法,分别计算两组答案再合并。
代码实现:
算法:Meet-in-the-middle 算法 + 双指针
思路:将 个数分成两组,分别用 map 存储,再分别处理两个 map 的子集和,然后合并,最后用双指针查找并输出结果。
AC Code:
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
vector<long long> v={
345590635693812, 411735179294186, 190029355501347, 973598561303630,
18202819016954, 739089526396984, 41064501651340, 287075700776565,
458062562307032, 723278851371706, 997720296178889, 470475557480472,
329586527903215, 907379737442406, 631284976214798, 301204036247736,
747294692547790, 914091289062262, 144070679727924, 988094642462741,
413975599277375, 835461430976017, 344371572186185, 646160866308904,
880407857470630, 794629069521762, 462180977651587, 342038139286302,
854772507978666, 694223418935656, 567502001946067, 881035713848915,
840605474892139, 324727089144326, 226008847101330, 65143946718125,
499249957077991, 245803813100131, 447887480320685, 658036302578844
};
int n=v.size();
int p=n/2;
//预处理前半部分的所有可能子集和
unordered_map<long long,long long> l;
for(int h=0;h<(1<<p);h++){
long long sum=0;
for(int i=0;i<p;i++){
if(h&(1<<i)) sum+=v[i];
}
l[h]=sum;
}
//预处理后半部分的所有可能子集和
unordered_map<long long,long long> r;
for(int h=0;h<(1<<(n-p));h++){
long long sum = 0;
for (int i=0;i<(n-p);i++){
if (h&(1<<i))sum+=v[p+i];
}
r[h]=sum;
}
long long t=0;
for (auto p : v) t+=p;
long long ans=t/2;
long long mi=LLONG_MAX;
//合并两部分结果
vector<long long> lv,rv;
for (auto& p : l) lv.push_back(p.second);
for (auto& p : r) rv.push_back(p.second);
sort(lv.begin(),lv.end());
sort(rv.begin(),rv.end());
//双指针查找最接近ans的和
int i=0,j=rv.size()-1;
while(i<lv.size()&&j>=0){
long long sum=lv[i]+rv[j];
mi=min(mi,abs(t-2*sum));
if(sum<ans){
i++;
}else if(sum>ans){
j--;
}else{
return 0; //找到完美分割
}
}
cout<<mi;
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...