Hướng giải của Đếm tập con tổng ≤ S
Nhớ rằng hướng dẫn giải này chỉ nên sử dụng khi bế tắc, và tuyệt đối không nên sao chép mã nguồn kèm theo. Hãy tôn trọng tác giả bài tập và người viết hướng dẫn giải.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.
Tác giả:
Lời giải: Meet in the middle
Phân tích
Chia mảng làm hai nửa. Duyệt mọi tập con của nửa trái, lưu tổng vào vector. Sắp xếp. Với mỗi tập con nửa phải, đếm số tập con nửa trái có tổng \(\le S - sum\_right\).
Code mẫu C++
#include <bits/stdc++.h>
using namespace std;
int main() {
int n; long long S; cin >> n >> S;
vector<long long> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
int n1 = n / 2, n2 = n - n1;
vector<long long> left;
for (int mask = 0; mask < (1 << n1); mask++) {
long long sum = 0;
for (int i = 0; i < n1; i++) if (mask & (1 << i)) sum += a[i];
left.push_back(sum);
}
sort(left.begin(), left.end());
long long ans = 0;
for (int mask = 0; mask < (1 << n2); mask++) {
long long sum = 0;
for (int i = 0; i < n2; i++) if (mask & (1 << i)) sum += a[n1 + i];
ans += upper_bound(left.begin(), left.end(), S - sum) - left.begin();
}
cout << ans << endl;
return 0;
}
Nhận xét