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; }