Bài tập về phép toán bit

Đề bài Gán bit thứ k trong số n về giá trị 0. Biết rằng bit đầu tiên bên tay trái là bit thứ 1.
INPUT: Hai số nguyên không âm n và k. Biết rằng n không quá 2 tỷ và k không quá 31.

Em muốn hỏi cách làm bài này . Ví dụ từ 37-> 33
Chỉ được viết trong cout << <<
Không được dùng ; , class

Hi Bảo Đỗ.
Chắc and bit hay or bit gì đó.

3 Likes

Em có hướng làm là lấy n-2^(k-1). Thì có cách nào viết trong đúng 1 cout kh ạ ??

1 Like

Cách bạn nêu không ổn, vì nếu bit thứ k mà bằng 0 thì nó vẫn trừ, sẽ bị sai kết quả.
Thay vào đó, dùng phép toán and sẽ hay hơn.
Ta có bảng chân trị.

0 and 0 = 0 (*)
0 and 1 = 0
1 and 0 = 0 (*)
1 and 1 = 1

Chú ý đến dòng 1 và 3, nó cho thấy một bit and với 0 sẽ cho ra 0 (tắt bit).
Ngược lại, nếu and với 1 sẽ cho ra chính nó (giữ nguyên).
Như vậy, ta cần n and x nào đó, mà số x nào có dạng 11111011 tại vị trí cần tắt bit.

Bài toán của bạn có một chút rắc rối ở chỗ là đếm thứ tự k từ trái sang phải, bạn cần chuyển vị trí k từ phải sang trái cho dễ (ở đây mình lấy 8 bit số nguyên)

k = 8 + 1 - k;
x = (2^8 - 1) - 2^(k - 1);

Cuối cùng, kết quả sẽ là n and x. Như ví dụ trên của bạn, n = 37 (00100100), k = 6 (mình tự cho theo kết quả vì input của bạn chưa cho). Chuyển đổi k thành bit thứ 3 từ phải qua trái. Suy ra x = (2^8 - 1) - 2^(k-1) = 255 - 4 = 251. Kết quả 37 and 251 = 33.

4 Likes

mình nghĩ là như thế này:
dùng kiểu int vì nó là 32bit (đủ giới hạn đề là 2 tỉ)
theo qui ước chuẩn thì bit đầu tiên bên tay phải là bit 0.
vậy phải chuyển từ k thành 32 - k

cout << (n & ((~0) ^ (1 << (32 - k))));
2 Likes

n & (~(1<<k-1))
Em dùng cái này nó cũng ra. Có thể giải thích cho em 1 xíu về câu lệnh được k ạ. Em mới học mà thầy cho bài như vậy @@
Còn 1 bài nữa à Tìm giá trị của bit thứ k trong n. Biết rằng bit đầu tiên bên tay phải là bit thứ 0.

mà đề yêu cầu chỉ được viết được trogn 1 cout ấy ạ @@

bài này thì đơn giản thôi.
cout << ((n >> k) & 1);

còn bài trên ý tưởng là ntn:
~0 để tạo ra 1 số nhị phân gồm toàn 32 bit 1 (111111…)
XOR với (1 << (32 - k)) là xor với dãy nhị phân, có bit 0 là 1, dịch qua 32 - k bit qua tay trái, sẽ tắt bit ở vị trí 32 - k của dãy ~0.
cuối cùng là AND, vị trí 32-k của n sẽ bị tắt bit, trạng thái của các bit còn lại giữ nguyên (vì còn lại là 1, mà ở 32-k nó lại là 0, khi AND thì chắc chắn vị trí đó của n sẽ thành 0).
Bạn làm thử bằng tay phép toán này sẽ hiểu.

2 Likes

cout<< n | (1<<k) & (1<<(k+1))

3 Likes
cout << "N: " << n << " , ret: " << (n &= ~(1UL << k)) ;
1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?