Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Hướng tiếp cận
Yêu cầu là tính, với mỗi mask , tổng . Đây là dạng "Sum Over Subsets" (SOS) cổ điển.
Cách duyệt trực tiếp tốn (mỗi bit có 3 lựa chọn: không thuộc , thuộc và thuộc , thuộc nhưng không thuộc ). Với , phép cộng — không khả thi trong 2 giây.
Nhận xét quan trọng
SOS DP biến đổi bài toán thành chuỗi phép quét, mỗi phép quét xử lý đúng một chiều bit. Sau khi xử lý xong bit , giá trị tạm thời là tổng của trên mọi tập con của mà và trùng nhau ở các bit . Cuối cùng, sau vòng, chính là tổng cần tìm.
Công thức truy hồi cho từng bit :
- Nếu bit của bằng : không đổi.
- Nếu bit của bằng : (cộng thêm phần đóng góp khi bit của bằng ).
Thuật toán
g[m] = f[m] với mọi m
for i in 0 .. N-1:
for m in 0 .. 2^N - 1:
if m & (1 << i):
g[m] += g[m ^ (1 << i)]
Thứ tự vòng lặp rất quan trọng: bit phải nằm vòng ngoài, mask vòng trong. Nếu đảo lại ( ngoài, trong) thì kết quả sẽ sai vì khi đến bit , các giá trị chưa đầy đủ qua các bit còn lại.
Lưu ý kiểu dữ liệu: có thể tới , dùng long long trong C++.
Độ phức tạp
- Thời gian: phép cộng khi .
- Bộ nhớ: số 64-bit, khoảng 8 MB.
Bình luận