Atcoder Beginner Contest 184F Programming Contest 题解

Topic link

Personally think it is a very good thinking question, using the idea of ​​two-way wide search

First of all, you should think of O ⁡ (2 N) \operatorname{O}(2^N)O ( 2The violence of N )
Next, we divide the original sequence into lengths ofn, mn, mn,The two paragraphs of m , and use the above violence method to enumerate the two paragraphs separately, and put each combination ofA i A_iAiThe sum is stored in an array. Here set a, ba, ba,The b array maintains two segments respectively.
Obviously, any plan in the first paragraph can be combined with any plan in the second paragraph.
So, now we only need to ask for the largest that does not exceedTTT a i + b j a_i+b_j ai+bjThe maximum value of,
then we will bbb array sorting. Then for eachai a_iai, Use dichotomy to find the largest one that satisfies ai + bj ≤ T a_i+b_j\le Tai+bjT 'sbj b_jbjAnd update the answer. The correctness is obvious.

n ≤ mn \ le mnm , the total complexity isO ⁡ (n ⋅ 2 m) \operatorname{O}(n\cdot 2^m)O ( n2m )
Obviously, whenn = m = N 2 n=m=\frac{N}{2}n=m=2NWhen the complexity is optimal, it can reach O ⁡ (n ⋅ 2 N) \operatorname{O}(n\cdot \sqrt{2^N})O ( n2N )

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const long long Maxn=45;
vector <long long> a,b;
long long c[Maxn];
long long n,m,ans;
inline long long read()
{
    
    
	long long s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
int main()
{
    
    
	n=read(),m=read();
	for(long long i=1;i<=n;++i)
	c[i]=read();
	long long cnt=(n>>1);
	for(long long x=0;x<(1<<cnt);++x)
	{
    
    
		long long ret=0;
		for(long long i=1;i<=cnt;++i)
		if((x>>(i-1)) & 1)ret+=c[i];
		a.push_back(ret);
	}
	cnt=n-cnt;
	long long tmp=(n>>1);
	for(long long x=0;x<(1<<cnt);++x)
	{
    
    
		long long ret=0;
		for(long long i=1;i<=cnt;++i)
		if((x>>(i-1)) & 1)ret+=c[i+tmp];
		b.push_back(ret);
	}
	sort(a.begin(),a.end()); // 比赛时没想那么多,直接两个都排序了
	sort(b.begin(),b.end());
	tmp=b.size();
	for(long long i=0;i<a.size();++i)
	{
    
    
		if(a[i]>m)break;
		if(a[i]+b[tmp-1]<=m)
		{
    
    ans=max(ans,a[i]+b[tmp-1]);continue;}
		long long l=0,r=b.size()-1;
		while(l<r)
		{
    
    
			long long mid=(l+r)>>1;++mid;
			if(a[i]+b[mid]<=m)l=mid;
			else r=mid-1;
		}
		ans=max(ans,a[i]+b[l]);
	}
	printf("%lld\n",ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/Brian_Pan_/article/details/109967567