(CodeForces) E. Maximum Subsequence (折半搜索)

傳送門

解題思路:一開始並不知道折半搜索這個算法,無論如何都不知道將2^35這麼多種情況壓縮,在1e9的複雜度解決出來,折半搜索就是將序列a分成兩個部分,分別去解決每個部分的子集,那也就最多2^18中情況。然後當我們選中一部分的一個子集x時,去第二個部分中找小於m-x最大的(二分),這樣就完美解決了,喵啊。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define sz(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b)	for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-9;
const int maxn=1<<18+5;
ll n,m,a[40],ta[maxn],tb[maxn],cnta,cntb;
il void dfs(ll sum,ll step,bool fg) {
	if(fg && step==n/2+1) {
		ta[cnta++]=sum%m;
		return ;
	} else if(!fg && step==n+1) {
		tb[cntb++]=sum%m;
		return ;
	}
	dfs(sum+a[step],step+1,fg);
	dfs(sum,step+1,fg);
}
int main() {
	std::ios::sync_with_stdio(0);
	cin>>n>>m;
	rep(i,1,n)	cin>>a[i];
	dfs(0,1,1);
	dfs(0,n/2+1,0);
	ll ans=0,tp;
	sort(ta,ta+cnta),sort(tb,tb+cntb);
	for(int i=0; i<cnta; ++i) {
		tp=m-ta[i];
		ll x=lower_bound(tb,tb+cntb,tp)-tb;
		if(x==0)	ans=max(ta[i],ans);
		else ans=max(ans,ta[i]+tb[x-1]);
	}
	cout<<ans<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章