1. 程式人生 > 其它 >[題解] Topcoder 15279 SRM 761 Div 1 Level 3 SpanningSubgraphs DP,容斥

[題解] Topcoder 15279 SRM 761 Div 1 Level 3 SpanningSubgraphs DP,容斥

0s 表示一串 0,1s 表示一串 1。

x ^ 0s = x      x & 0s = 0      x | 0s = x
x ^ 1s = ~x     x & 1s = x      x | 1s = 1s
x ^ x = 0       x & x = x       x | x = x

利用 x ^ 1s = ~x 的特點,可以將一個數的位級表示翻轉;利用 x ^ x = 0 的特點,可以將三個數中重複的兩個數去除,只留下另一個數。
1^1^2 = 2
利用 x & 0s = 0 和 x & 1s = x 的特點,可以實現掩碼操作。一個數 num 與 mask:00111100 進行位與操作,只保留 num 中與 mask 的 1 部分相對應的位。

01011011 &
00111100
--------
00011000

利用 x | 0s = x 和 x | 1s = 1s 的特點,可以實現設值操作。一個數 num 與 mask:00111100 進行位或操作,將 num 中與 mask 的 1 部分相對應的位都設定為 1。

01011011 |
00111100
--------
01111111

mask 計算
要獲取 111111111,將 0 取反即可,~0。
要得到只有第 i 位為 1 的 mask,將 1 向左移動 i-1 位即可,1<<(i-1) 。例如 1<<4 得到只有第 5 位為 1 的 mask :00010000。
要得到 1 到 i 位為 1 的 mask,(1<<i)-1 即可,例如將 (1<<4)-1 = 00010000-1 = 00001111
要得到 1 到 i 位為 0 的 mask,只需將 1 到 i 位為 1 的 mask 取反,即 ~((1<<i)-1)。

技巧

  1. n&(n-1) 去除 n 的位級表示中最低的那一位 1。例如對於二進位制表示 01011011,減去 1 得到 01011010,這兩個數相與得到 01011010。
01011011 &
01011010
--------
01011010
  1. n&(-n) 得到 n 的位級表示中最低的那一位 1。-n 得到 n 的反碼加 1,也就是 -n=~n+1。例如對於二進位制表示 10110100,-n 得到 01001100,相與得到 00000100。
10110100 &
01001100
--------
00000100

n-(n&(-n)) 則可以去除 n 的位級表示中最低的那一位 1,和 n&(n-1) 效果一樣。