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;
} 
京公网安备 11010502036488号