Educational Codeforces Round 32 E 巨型背包

思路:n只有35, 将n份为2部分,一部分为前n/2个物品的取舍(取或不去), 另一部分为剩下物品的取舍,复杂度为2^(n/2),枚举左边的数,然后二分右边的数找到最优解,写lower_bound需要去重,手写二分就不需要了

AC代码:

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e5+100;

int a[N],ans;
vector<int> vex1, vex2;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i){
        scanf("%d",&a[i]);
        a[i]%=m;
    }
    int p=n>>1, q=n-p;
    for(int i=0; i<(1<<p); ++i){
        int u=0;
        for(int j=0; j<p; ++j){
            if(i&(1<<j)) u=(u+a[j+1])%m;
        }
        vex1.pb(u%m);
    }
    for(int i=0; i<(1<<q); ++i){
        int u=0;
        for(int j=0; j<q; ++j){
            if(i&(1<<j)) u=(u+a[j+p+1])%m;
        }
        vex2.pb(u%m);
    }
    sort(vex1.begin(), vex1.end()), unique(vex1.begin(), vex1.end());
    sort(vex2.begin(), vex2.end()), unique(vex2.begin(), vex2.end());
    for(auto u : vex1){
        int g=m-u;
        int it = lower_bound(vex2.begin(),vex2.end(),g) - vex2.begin()-1;
        if(it<0) continue;
        ans=max(ans, u+vex2[it]);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted on 2017-11-12 15:56  lazzzy  阅读(174)  评论(0编辑  收藏  举报

导航