Khoá học C++ nâng cao
Bài học: Phép Toán Bit & Mặt Nạ Bit Nâng Cao
🏆 +100 XP tiềm năng Thoát

Phép Toán Bit & Mặt Nạ Bit Nâng Cao

2 khối nội dung 45 phút học tập MỞ BẢNG TRẮNG

Phép Toán Bit & Mặt Nạ Bit Nâng Cao

Nội dung bài học

1. Khái niệm & bản chất của tối ưu hóa cấp độ bit (Bit Manipulation)

Trong kiến trúc máy tính hiện đại, các phép toán trên bit (AND, OR, XOR, NOT, dịch bit <<, >>) được CPU xử lý trực tiếp ở mức phần cứng trong đúng $1$ chu kỳ xung nhịp (clock cycle).

Ở Level 2, phép toán bit được nâng cấp thành Mặt nạ bit (Bitmask) để biểu diễn trạng thái của một tập hợp con:

  • Một số nguyên $M$ có thể đại diện cho một tập con của $N$ phần tử: bit thứ $i$ bật ($= 1$) nghĩa là phần tử thứ $i$ được chọn, bit thứ $i$ tắt ($= 0$) nghĩa là phần tử thứ $i$ không được chọn.
  • Duyệt toàn bộ $2^N$ tập con: Dùng vòng lặp for (int mask = 0; mask < (1 << N); ++mask).
  • Duyệt toàn bộ tập con của một mặt nạ bit (Submask Iteration): Duyệt tất cả submask của mask trong tổng thời gian $\mathcal{O}(3^N)$ thay vì $\mathcal{O}(4^N)$ bằng thủ thuật sub = (sub - 1) & mask.
  • Quy hoạch động trên mặt nạ bit (Bitmask DP): Giải các bài toán tối ưu trên tập hợp nhỏ ($N \le 20$) như bài toán Người du lịch (Traveling Salesperson Problem - TSP), ghép cặp hoàn hảo (Matching).

Bảng thao tác Bitmask

2. Bảng tổng hợp các thủ thuật Bitwise

Thao Tác Toán Học Biểu Thức C++ Chuẩn Ý Nghĩa / Mục Đích
Bật bit thứ $k$ mask \| (1 << k) Thêm phần tử $k$ vào tập hợp
Tắt bit thứ $k$ mask & ~(1 << k) Loại bỏ phần tử $k$ khỏi tập hợp
Đảo bit thứ $k$ mask ^ (1 << k) Chuyển đổi trạng thái có/không của $k$
Kiểm tra bit thứ $k$ (mask >> k) & 1 Trả về 1 nếu $k$ thuộc tập, 0 nếu không
Lấy bit 1 thấp nhất (LSB) mask & (-mask) Trích xuất bit 1 nhỏ nhất (cực kỳ hữu ích trong Fenwick Tree)
Tắt bit 1 thấp nhất mask & (mask - 1) Xóa bit 1 nhỏ nhất (dùng đếm số bit 1 của Brian Kernighan)
Đếm số bit 1 (Popcount) __builtin_popcount(mask) Số lượng phần tử trong tập hợp
Đếm số bit 0 ở đuôi __builtin_ctz(mask) Vị trí của bit 1 thấp nhất

3. Kỹ thuật duyệt Submask tối ưu $\mathcal{O}(3^N)$

Để duyệt tất cả các tập con $sub$ của một tập $mask$:

for (int mask = 0; mask < (1 << n); ++mask) {
    for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
        // Xử lý submask 'sub' của 'mask'
    }
}

Chứng minh độ phức tạp: Tổng số cặp $(mask, sub)$ là $\sum_{k=0}^N \binom{N}{k} 2^k = (1 + 2)^N = 3^N$. Với $N = 15$, $3^{15} \approx 1.4 \times 10^7$ phép tính (chạy trong $< 0.05\text{s}$).


4. Mẫu cài đặt chuẩn thi đấu: TSP với Bitmask DP

Bài toán Người du lịch: Tìm đường đi ngắn nhất thăm tất cả $N$ thành phố ($N \le 18$) xuất phát từ đỉnh 0.

#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;
int n;
int dist_mat[20][20];
int dp[1 << 18][18]; // dp[mask][u]: Chi phí nhỏ nhất đi qua tập các đỉnh trong 'mask' và kết thúc tại u

int tsp(int mask, int u) {
    if (mask == (1 << n) - 1) return dist_mat[u][0]; // Quay về đỉnh 0
    if (dp[mask][u] != -1) return dp[mask][u];

    int ans = INF;
    for (int v = 0; v < n; ++v) {
        if (!((mask >> v) & 1)) { // Nếu đỉnh v chưa thăm
            ans = min(ans, dist_mat[u][v] + tsp(mask | (1 << v), v));
        }
    }
    return dp[mask][u] = ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    if (!(cin >> n)) return 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) cin >> dist_mat[i][j];
    }

    memset(dp, -1, sizeof(dp));
    cout << tsp(1, 0) << "\n"; // Bắt đầu tại đỉnh 0 với mask = 1 (chỉ mới thăm đỉnh 0)
    return 0;
}

5. Ranh giới áp dụng

Phạm Vi $N$ Kỹ Thuật Tối Ưu Độ Phức Tạp
$N \le 20$ Bitmask DP / Quy hoạch động trạng thái $\mathcal{O}(2^N \times N^2)$ hoặc $\mathcal{O}(3^N)$
$N \le 30$ Meet in the Middle / Phân đôi tập hợp $\mathcal{O}(2^{N/2})$
$N \le 10^5$ Greedy / Tree DP / Khử bit trực tiếp $\mathcal{O}(N \log N)$

1
A
B
C
D
2
A
B
C
D

Bài tập lập trình vận dụng

24 Bài tập thực hành

Nhấn vào nút "Làm bài" bên dưới để mở giao diện làm bài trực tuyến (Online Judge) và thực hiện viết mã nguồn cho bài tập này.

Bài toán người du lịch (tsp)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đếm số phần tử bật BIT chung (bitwise and)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Bài toán người du lịch (tsp bitmask DP)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Phân chia công việc hoàn hảo (job assignment)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Duyệt tất cả submask tính tổng phân hoạch
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đường đi hamilton đếm số cách
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối đa hóa giá trị xor đoạn con bằng Trie BIT
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Ghép cặp trọng số cực đại (maximum matching bitmask)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Sos DP (sum over subsets dynamic programming)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Đếm số cặp $(a_i, a_j)$ có tích and bằng 0
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Sos DP (sum over subsets dynamic programming)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tô màu đồ thị số lượng màu nhỏ nhất (graph coloring)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tìm chu trình hamilton chi phí nhỏ nhất
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tập độc lập trọng số lớn nhất trên đồ thị nhỏ
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Phân hoạch tập hợp thành k tập con có tổng bằng nhau
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Tối ưu hóa trò chơi nim tổng quát (sprague-grundy BIT)
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Sos DP sum over subsets
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Profile DP lat gach domino
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Bien doi FWT bitwise xor
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dem tap doc lap cuc dai
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Bitmask DP phan nhom k tap
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Xor basis vector khong gian tuyen tinh
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Bitmask ghep doi trong so cuc dai
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài
Dem duong di hamilton bitmask
Độ khó: mediumĐiểm tối đa: 100.0 điểm
Làm bài