Xử lý bit - Pascal

(Nguồn: http://ptthlamson.net/forums/showthread.php?t=8802)

Trong một số bài toán cần đánh dấu, ta thường phải dùng 1 biến logic, mất đi 1 byte bộ nhớ. Trong khi thực ra ta chỉ cần dùng 1 bit để ghi nhận trạng thái. Như vậy là ta đã lãng phí đi mất 7 bít còn lại. Có một cách để không bị lãng phí đi 7 bit kia là xử lí bit nghĩa là ta sẽ truy cập trực tiếp vào từng bit một của mỗi byte.

Ta xét bài toán sau đây:

Với 1 dãy số ta có 2 phép toán

  1. Thêm số x vào dãy số
  2. Đưa ra xem số x có xuất hiện trong dãy hay chưa. (1: có, 0: không)
    Ban đầu dãy số rỗng.
    Hãy thực hiện lần lượt 1 số phép toán trên dãy.

Input:

  • Dòng đầu là số m - số phép toán cần thực hiện. (m <= 100000)
  • m dòng sau mỗi dòng gồm 2 số nguyên k, x. k là loại phép toán, x là giá trị tương ứng (0 <= x <= 450000);

Output

  • Đưa ra kết quả tương ứng với phép toán 2.

Bài này m và x khá lớn. Nếu ta đánh dấu thông thường thì chỉ chạy được với x <= 65000. Nhưng nếu xử lý bit thì ta có thể chạy được hết dữ liệu. ^^
Cụ thể:
Ta có 1 mảng byte 60000 phần tử => có 480000 bit. Mỗi bit sẽ tương ứng với 1 số x.
Ban đầu khởi tạo mảng là 0 hết vì chưa có số nào xuất hiện.
Với 1 số x thì ta sẽ xác định vị trí của nó là bit thứ (x mod 8) của phần tử (x div 8).
(chú ý các bit trong máy tính đánh số từ 0)
Giờ khi thêm 1 số x vào dãy thì ta bật bit tương ứng của x lên.
Khi kiểm tra xem x có trong dãy hay không thì ta chỉ việc lấy giá trị của bit tương ứng với x.

Ta có 2 phép toán sau trên 1 số:

  • x shl k: dịch dãy bit của x sang trái k vị trí
  • x shr k: dịch dãy bit của x sang phải k vị trí

Thủ tục bật bit thứ k của 1 số a.

procedure BatBit(k: byte; var a: byte);
begin
a := a or (1 shl k);
end;

Hàm lấy bit thứ k của 1 số a.

function GetBit(k, a: byte): byte;
begin
GetBit := 1 and (a shr k);
end;

Như vậy là ta đã có thể giải quyết xong bài toán này.

Ngoài ra ta còn có thể tắt bit của số a:

procedure TatBit(k: byte; var a: byte);
begin
a := a and not (1 shl k);
end;

Đảo bit

procedure DaoBit(k: byte; var a: byte);
begin
a := a xor (1 shl k);
end;

Không chỉ có tác dụng giảm bộ nhớ. Việc xử lý bit còn có thể giúp ta cài đặt dễ dàng hơn trong 1 số bài toán cụ thể như khi cần ghi nhận trạng thái của 1 dãy 15 bóng đèn (sáng tắt) thì đó chính là 1 dãy 15 bit tương ứng với cách biểu diễn 1 số kiểu integer trong hệ nhị phân. Từ đó có thể dễ dàng đánh dấu trạng thái để giải quyết bài toán!

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?