题意
完全背包 ( n ≤ 1 0 6 , m ≤ 1 0 16 , a i , b i ≤ 100 ) (n\leq10^6,m\leq10^{16},a_i,b_i\leq100) (n≤106,m≤1016,ai,bi≤100)
思路
m
m
m很大,
O
(
n
m
)
O(nm)
O(nm)直接
G
G
GG
GG。
但是发现
a
i
,
b
j
≤
100
a_i,b_j\leq100
ai,bj≤100,所以最多选
100
100
100种物品。获得了
60
60
60分的好成绩。
其实我们能发现一个大背包能由若干个小背包组成,并且
所以对于每种容量的背包,把它选完,剩下的用剩下容量的背包填补。
代码
#include <cctype>
#include <cstdio>
#include <algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline long long read() {
long long res = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') f = 1;
ch = getchar();
}
while (isdigit(ch)) {
res = res * 10 + ch - 48;
ch = getchar();
}
return f ? -res : res;
}
long long n, m, ans;
int a[101];
long long f[5052];
int main() {
file(backpack);
n = read();
m = read();
for (register int i = 1; i <= n; i++) {
int x = read(), y = read();
a[x] = std::max(a[x], y);
}
for (register int i = 1; i <= 100; i++)
for (register int j = i; j <= 5051; j++)
f[j] = std::max(f[j], f[j - i] + a[i]), ans = std::max(ans, m / j * f[j] + f[m % j]);
printf("%lld", ans);
}