Skip to main content
📜 WAYPOINT LESSON

Counting Variants — Subsets and Exact Fill

⭐⭐ intermediate⏳ 18 min read📍 Lesson 101 of 281

Same tables, counts instead of maxima: add instead of max, and watch the modulus; exact fill means the rest of the table stays at zero/INF.

Đếm tập con có tổng T

dp[s] = số tập con có tổng s. Mỗi món một lần → NGƯỢC, và phép hợp thay max là CỘNG:

vector<long long> dp(T + 1, 0);
dp[0] = 1;
for (int i = 0; i < n; ++i)
    for (int s = T; s >= a[i]; --s)
        dp[s] = (dp[s] + dp[s - a[i]]) % MOD;

dp[0] = 1 là "tập rỗng" — quên nó làm mọi kết quả lệch đúng một lớp. Xuôi vòng → đếm "dùng lại" — kết quả phình: test phân biệt phải có phần tử lặp lại nhỏ.

Chia đôi mảng

Tổng S; hỏi tách thành hai nửa BẰNG NHAU ⇔ tồn tại tập con tổng S/2. S lẻ → NO ngay (không cần DP). Sẵn sàng boolean dp[0..S/2]:

vector<char> dp(half + 1, 0);
dp[0] = 1;
for (int i = 0; i < n; ++i)
    for (int s = half; s >= a[i]; --s)
        if (dp[s - a[i]]) dp[s] = 1;

Lấp ĐÚNG sức chứa

Variant khó hơn max-thường: chọn món sao cho TỔNG TRỌNG LƯỢNG ĐÚNG BẰNG W (không thừa không thiếu), tối đa giá trị; không được → in −1. dp[j] = giá trị tốt nhất đạt TỔNG ĐÚNG j; khởi tạo −INF, dp[0] = 0:

const long long NEG = -(1LL << 60);
vector<long long> dp(W + 1, NEG);
dp[0] = 0;
for (int i = 0; i < n; ++i)
    for (int j = W; j >= w[i]; --j)
        if (dp[j - w[i]] != NEG)
            dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
if (dp[W] < 0) out << -1;

Khác biệt so với balo thường: những j không đạt ĐÚNG giữ −INF, không bao giờ góp vào kết quả. W "bal ≤ thường" sẽ in giá trị balo bình thường — sai khi lấp không đầy.

Nhận diện

  • "số cách" → cộng, mô-đun, cẩn thận dp[0] = 1.
  • "tách hai nửa" → subset-sum về S/2.
  • "đúng sức chứa / đúng tổng" → nền −INF thay vì 0.

Điểm mấu chốt: đếm = max đổi thành cộng (mô-đun!); exact = −INF nền; mọi variant vẫn còn chiềuu duyệt quyết định tái sử dụng.

⚡ Now practice

Ready to Code
Knapsack Problem SetFive problems: 0/1 knapsack, min coins unbounded, subset counting, equal partition, exact fill.
5 challenges · · ~50 min