T3

Solution

我们先判断答案是否存在,即这几个物品能否凑成,如果不能,答案则为
否则的话,我们易知:不同体积的物品不超过个。
我们可以用分治的思想来解决该题。
表示保留区间的物品,其余的物品已经塞入背包时的状态,我们用一个bitset来维护。
那么,考虑如何分治转移。
,则当我们要进行时,就先将的物品依次插入; 同理。
复杂度,可以通过

Code

下面是我考场写的丑陋代码

// Author: wlzhouzhuan
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ull unsigned long long
#define rint register int
#define rep(i, l, r) for (rint i = l; i <= r; i++)
#define per(i, l, r) for (rint i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define mp(a, b) make_pair(a, b)

inline int read() {
  int x = 0, neg = 1; char op = getchar();
  while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); }
  while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); }
  return neg * x;
}
inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 100001;
int a[N], n, m;
int vis[100001];

struct node {
  int x, tim;
} b[N];

vector <int> _ans;
void solve(int l, int r, bitset <100001> dp) {
  if (dp[m]) return ;
  if (l == r) {
    _ans.pb(b[l].x);
    return ;
  }
  int mid = l + r >> 1;
  bitset <100001> f = dp;
  for (int i = mid + 1; i <= r; i++) {
    for (int j = 1; j <= b[i].tim; j++) {
      f |= f << b[i].x;
    }
  }
  solve(l, mid, f);
  bitset <100001> g = dp;
  for (int i = l; i <= mid; i++) {
    for (int j = 1; j <= b[i].tim; j++) {
      g |= g << b[i].x;
    }
  }
  solve(mid + 1, r, g);
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
  }

  bitset <100001> all;
  all.set(0);
  for (int i = 1; i <= n; i++) {
    all |= all << a[i];
  }
  if (!all[m]) {
    puts("0");
    exit(0);
  }

  if (n <= 20) {
    vector <int> ans;
    for (int i = 1; i <= n; i++) {
      if (vis[a[i]]) continue;
      vis[a[i]] = 1;
      bitset <100001> dp;
      dp.set(0);
      for (int j = 1; j <= n; j++) if (a[i] != a[j]) {
        dp |= dp << a[j];
      }
      if (!dp[m]) {
        ans.pb(a[i]);
      }
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    for (auto v: ans) {
      printf("%d ", v);
    }
    puts("");
  } else if (n <= 200 && m <= 1000) {
    vector <int> ans;
    for (int i = 1; i <= n; i++) {
      if (vis[a[i]]) continue;
      vis[a[i]] = 1;
      bitset <1001> dp;
      dp.set(0);
      for (int j = 1; j <= n; j++) if (a[i] != a[j]) {
        dp |= dp << a[j];
      }
      if (!dp[m]) {
        ans.pb(a[i]);
      }
    }
    sort(ans.begin(), ans.end());
    printf("%d\n", ans.size());
    for (auto v: ans) {
      printf("%d ", v);
    }
    puts("");
  } else {
    sort(a + 1, a + n + 1);
    int nn = 0;
    for (int i = 1; i <= n; i++) {
      int j = i;
      while (j < n && a[j + 1] == a[i]) j++;
      b[++nn] = {a[i], j - i + 1};
      i = j;
    }
    n = nn;
    bitset <100001> _ff;
    _ff.set(0);
    solve(1, nn, _ff);
    sort(_ans.begin(), _ans.end());
    printf("%d\n", _ans.size());
    for (auto v: _ans) {
      printf("%d ", v);
    }
    puts("");
  }
  return 0;
}