Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

bit演算

ビット演算は整数をビット列として扱い、各ビットに対して論理演算やシフト演算を行う。高速・省メモリなため、競技プログラミングや低レベルプログラミングで頻繁に使われる。

演算子名前例 (a=0b1010, b=0b1100)結果
&ANDa & b0b1000
|ORa | b0b1110
^XORa ^ b0b0110
~NOT~a-11(2の補数)
<<左シフトa << 10b10100
>>右シフトa >> 10b0101
a     = 1010 (10)
b     = 1100 (12)
a & b = 1000 (8)
a | b = 1110 (14)
a ^ b = 0110 (6)
a << 1= 10100 (20)
a >> 1= 0101 (5)

ビットマスク

1 << k で k ビット目だけが立ったマスクを作り、特定ビットの操作を行う。

操作コード
k ビット目を立てる(set)x | (1 << k)
k ビット目を消す(clear)x & ~(1 << k)
k ビット目を反転(toggle)x ^ (1 << k)
k ビット目を取得(get)(x >> k) & 1
x                              = 0101 (5)
set bit 1   : x | (1<<1)       = 0111 (7)
clear bit 2 : x & ~(1<<2)      = 0001 (1)
toggle bit 0: x ^ (1<<0)       = 0100 (4)
get bit 2   : (x>>2)&1         = 1

よく使うイディオム

2の累乗判定

n & (n - 1) == 0 が成り立つとき n は 2 の累乗(n > 0 を前提)。

なぜ? 2の累乗は 100...0 の形。n - 1 は 011...1 になるので AND が 0 になる。

最下位ビットの取り出し(LSB)

n & (-n) で最下位の立っているビットだけを取り出せる。Fenwick Tree(BIT)の根幹。

立っているビット数(ポップカウント)

bin(n).count('1') または n.bit_count()(Python 3.10+)。

is_power_of_2( 0) = False
is_power_of_2( 1) = True
is_power_of_2( 2) = True
is_power_of_2( 3) = False
is_power_of_2( 4) = True
is_power_of_2( 6) = False
is_power_of_2( 8) = True
is_power_of_2(16) = True

n   = 10110 (22)
LSB = 00010 (2)

popcount(00000000) = 0
popcount(00001010) = 2
popcount(00001111) = 4
popcount(11111111) = 8

応用:部分集合の列挙(ビット全探索)

n 個の要素からなる集合の全部分集合を 0 から 2^n - 1 までのビット列で表現する。各ビットが「その要素を選ぶかどうか」に対応する。計算量は O(2^n)。

全部分集合:
  000 -> []
  001 -> ['A']
  010 -> ['B']
  011 -> ['A', 'B']
  100 -> ['C']
  101 -> ['A', 'C']
  110 -> ['B', 'C']
  111 -> ['A', 'B', 'C']

values=[1, 3, 5, 7], target=8 になる部分集合:
  [3, 5]
  [1, 7]

応用:ビット DP

状態を集合(ビット列)で表すDPをビットDPという。典型例として巡回セールスマン問題(TSP)がある。

dp[S][v] = 頂点集合 S を訪問済みで、現在頂点 v にいるときの最小コスト。

dp[S∣(1<<u)][u]=min⁡(dp[S∣(1<<u)][u],  dp[S][v]+cost[v][u])dp[S | (1 << u)][u] = \min(dp[S | (1 << u)][u], \; dp[S][v] + \text{cost}[v][u])

計算量: O(2^n × n^2)

TSP最小コスト: 21