usaco 2.1.4

直接枚舉,然後用位運算計算二進制表示時1的個數。代碼:

matrix67有關位運算的講解實在是太好了,終於派上用場了,現在摘取一些,方便以後查閱。

Pascal和C中的位運算符號
    下面的a和b都是整數類型,則:
C語言  |  Pascal語言
-------+-------------
a & b  |  a and b
a | b  |  a or b
a ^ b  |  a xor b
  ~a   |   not a
a << b |  a shl b
a >> b |  a shr b

 

一個看起來非常詭異的swap過程:
procedure swap(var a,b:longint);
begin
   a:=a xor b;
   b:=a xor b;
   a:=a xor b;
end;

一些常見的二進制位的變換操作。

    功能              |           示例            |    位運算
----------------------+---------------------------+--------------------
去掉最後一位          | (101101->10110)           | x shr 1
在最後加一個0         | (101101->1011010)         | x shl 1
在最後加一個1         | (101101->1011011)         | x shl 1+1
把最後一位變成1       | (101100->101101)          | x or 1
把最後一位變成0       | (101101->101100)          | x or 1-1
最後一位取反          | (101101->101100)          | x xor 1
把右數第k位變成1      | (101001->101101,k=3)      | x or (1 shl (k-1))
把右數第k位變成0      | (101101->101001,k=3)      | x and not (1 shl (k-1))
右數第k位取反         | (101001->101101,k=3)      | x xor (1 shl (k-1))
取末三位              | (1101101->101)            | x and 7
取末k位               | (1101101->1101,k=5)       | x and (1 shl k-1)
取右數第k位           | (1101101->1,k=4)          | x shr (k-1) and 1
把末k位變成1          | (101001->101111,k=4)      | x or (1 shl k-1)
末k位取反             | (101001->100110,k=4)      | x xor (1 shl k-1)
把右邊連續的1變成0    | (100101111->100100000)    | x and (x+1)
把右起第一個0變成1    | (100101111->100111111)    | x or (x+1)
把右邊連續的0變成1    | (11011000->11011111)      | x or (x-1)
取右邊連續的1         | (100101111->1111)         | (x xor (x+1)) shr 1
去掉右起第一個1的左邊 | (100101000->1000)         | x and (x xor (x-1))


二進制中的1有奇數個還是偶數個
var
   x:longint;
begin
   readln(x);
   x:=x xor (x shr 1);
   x:=x xor (x shr 2);
   x:=x xor (x shr 4);
   x:=x xor (x shr 8);
   x:=x xor (x shr 16);
   writeln(x and 1);
end.

 

計算二進制中的1的個數
x := (x and $55555555) + ((x shr 1) and $55555555);
x := (x and $33333333) + ((x shr 2) and $33333333);
x := (x and $0F0F0F0F) + ((x shr 4) and $0F0F0F0F);
x := (x and $00FF00FF) + ((x shr 8) and $00FF00FF);
x := (x and $0000FFFF) + ((x shr 16) and $0000FFFF);

 

二分查找32位整數的前導0個數
int nlz(unsigned x)
{
   int n;

   if (x == 0) return(32);
   n = 1;
   if ((x >> 16) == 0) {n = n +16; x = x <<16;}
   if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
   if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
   if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
   n = n - (x >> 31);
   return n;
}

 

 

發佈了22 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章