3
1

bit演算云々について

Last updated at Posted at 2024-07-23

yukicoder No.3 ビットすごろくの解説を書いていた。それがビットに関する問題だったので、記念してこの記事を書く。
bit問題とは、基本的にはbit全探索のために使うbitと、bitの考え方を使うbitの二種類があると思っている。この記事では、主に後者をまとめることにする。
ABC-Cはbit全探索のbitしか基本的にはでないが、D以降になると後者のものも増える。
よって、ビットに関する知識はD以降の正答率を少し押し上げるはずだと思っている。

前提知識:ビット表記

そもそもの話だが、ビット表記は2進法になる。たとえば
・6は110になる
・19は10011になる
・32は100000になる
こんな感じ。
右から見てi桁目は$2^{i-1}$の位を表す。
この表記を知らないと話ができないので、先に説明した。

ビット演算子

一般的に出てくるビット演算子は3つ。&と|と$\oplus$だ。
もちろん、記号だけだとわからないと思うので、どのようなものかを説明する。

論理積

&は、論理積(AND)というものを求める記号である。

x y xANDy
0 0 0
0 1 0
1 0 0
1 1 1

こんな感じで、xとyともに1になっているもののみ1にするという記号だ。

・1&3=1
・3&6=2
・4&9=0

論理和

|は、論理和(OR)というものを求める記号である。

x y xORy
0 0 0
0 1 1
1 0 1
1 1 1

こんな感じで、xとyどちらかが1になっているものを1にするという記号だ。

・1|3=3
・3|6=2
・4|9=13

排他的論理和

$\oplus$は、排他的論理和(XOR)というものを求める記号である。

x y xXORy
0 0 0
0 1 1
1 0 1
1 1 0

こんな感じで、xとyどちらかのみ1になっているものを1にするという記号だ。

・1$\oplus$3=2
・3$\oplus$6=5
・4$\oplus$9=13

基本的に、bitをうんたらかんたらするタイプの問題は、上記のものを理解していれば何を言ってるかがわかるものが多い。

その他、覚えておきたいビットに関する関数

上記のものほどではないが、よく使う関数について説明する。

builtin_popcount

これはbit列に直したときに、1の出てくる数という意味である。

・5=101=2
・25=11001=3
・125=1111101=6
なお、一般的に問題文に出るときはpopcountと呼ばれる。

これだけである。ほかにあるのかもしれないが、基本的にこれだけ覚えておけば大半は対処できる。

C++におけるビット系の扱い方

まず、注意してほしいのが排他的論理和を求める記号が^であることだ。これさえ覚えておけば、基本的に問題はない。

ビット列を作るとき

使用例:bitset<60> $e$(50)
<>の中の数字は、作るbit列の長さについて(中の数字は常に定数でないとならない)。
ダメな例:bitset<$k$> $e$(50)

()の中には、基本的に数字を入れることで中の数字をビット列に直す。という使い方が大半。

ビット演算子について

ビット演算子は変数にも使える。これを覚えておこう。
論理積→&
論理和→&
排他的論理積→^
こういう対応をしている

builtin_popcountの使い方

ビット列eに対してe.count()で求まる。

ビット問題への考え方

D - Popcount and XOR
実行時間制限: 2 sec / メモリ制限: 1024 MB
配点 : 400 点
問題文
非負整数 $a,b,C$ が与えられます。 次の 5 つの条件をすべて満たす非負整数の組 $(X,Y)$ が存在するか判定し、存在するならひとつ出力してください。
・$0≤X<2^{60}$
・$0≤Y<2^{60}$
・$popcount(X)=a$
・$popcount(Y)=b$
・$X⊕Y=C$
ただし、⊕ はビットごとの排他的論理和を表します。
条件を満たす $(X,Y)$ が複数存在する場合、どれを出力しても構いません。
制約
$N$ は $0$ 以上 $2^{60}$ 未満の整数
$M$ は $0$ 以上 $2^{60}$ 未満の整数
ABC347-Dより

D - Masked Popcount
実行時間制限: 2 sec / メモリ制限: 1024 MB
配点 : 400 点
問題文
整数 $N,M$ が与えられるので、
$\sum_{k=0}^N$ $popcount(k$&$M)$ を $998244353$ で割った余りを求めてください。
ただし、 & はビット単位 AND 演算を表します。
制約
$N$ は $0$ 以上 $2^{60}$ 未満の整数
$M$ は $0$ 以上 $2^{60}$ 未満の整数
ABC356-Dより

このような一般にbitと絡める問題はとある事実を知るだけで見通しがかなり良くなる。それが各bitは独立しているという事実である。
ビット列の$2^3$桁目が変わっても$2^5$桁目は変わらない。その事実だ。
この考えの有効性を理解するのなら下の問題の方がいいだろう。
$M$の$2^i$桁目について考えるときに、$M$の$2^{i+1}$桁目が影響することはない。よって、各桁の解をいい感じに求めてしまえば、あとはそれを足すだけ。この考えを知っただけで、問題への感じ方がだいぶ変わっただろう。

まとめ

結果から言うと、言いたかったのは最後の独立性のみである。この考えを持っていれば、さらにビット演算の使い方を理解すれば、かなりビット演算問題も解きやすくなるのではなかろうか。

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1