• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

bit演算

date: 2021-04-22 excerpt: bit演算について

tag: bit operationbit演算


bit演算について

  • pythonでも高速にbit演算を行うことができる
  • bit全探索等の広い応用先がある

演算

&(and)オペレータ

2 & 6 
=> 2

|(or)オペレータ

2 | 6
=> 6

^(xor)オペレータ

2^6 == (2|6)-(2&6)
=> True
  • 理論記号とベン図が参考になる

«オペレータ

\(2^k\)するのと同義
bit列で考えると、左にシフトするのと同義

3 << 4
=> 48 # 3*(2**4)と等しい

»オペレータ

\(2^k\)で割り込むのと同義
bit列で考えると、右にシフトするのと同義

12 >> 2
=> 3 # 12//(2**2)と等しい

応用; bit列の共起

\(n\)の整数で表されるbit列に整数\(i\)番の要素\(n\)の中に含まれるかどうかを判定する

def has_bit(n, i):
    return (n & (1<<i) > 0)

または

def has_j_index(n, i):
    return (n>>i) & 1 == 1:

応用; 10進数を2進数のリストに変換する

n = 10
b = [n >> i & 1 for i in range(n.bit_length()-1,-1,-1)]
b # [1, 0, 1, 0]が得られる

応用; 2進数のリストを10進数に変換する

print(b) # [1, 0, 1, 0]
[(x * 1<<i) for i, x in enumerate(reversed(b))] # [0, 2, 0, 8]が得られる
sum([(x * 1<<i) for i, x in enumerate(reversed(b))]) # 10になる

応用; bit全探索

  • brute forceで\(n\)個の要素があり\(n!\)個のパターンを試行する必要がある場合に高速に演算できる
  • 例えば、\([1,-2,3,-4,5,-6,7,-8,9,-10,11,-12]\)の列のどの要素を合計すると最大になるか探索する場合
import math
A = [1,-2,3,-4,5,-6,7,-8,9,-10,11,-12]
size = len(A)

ans = -math.inf
all_pattern = 1<<size
for i in range(all_pattern):
    acc = 0
    for j in range(len(A)):
	    # iを2進数としてみなした時、jビット目のフラグが立っているかどうか
        if i&(1<<j) != 0:
            acc += A[j]
    ans = max(ans, acc)
print(ans) # 36, print(sum([a for a in A if a >= 0]))と等しくなる

例; bit全探索

  • brute froceで仕切りのパターンを列挙するときにも用いることができる
  • nCn + nCn-1 + ... + nC1の列挙と等しい

問題

  • AtCoder Beginner Contest 197; C - ORXOR

回答

N=int(input())
A=list(map(int,input().split()))

import math
ans = math.inf

patterns = 1<<N
for i in range(1, patterns):
    tmp, total = 0, 0
    for j in range(N):
        tmp |= A[j]
        if i&(1<<j) > 0:
            total ^= tmp
            tmp = 0
    total ^= tmp
    ans = min(ans, total)
print(ans)


bit operationbit演算 Share Tweet