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