1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AtCoder対策 bit操作

Posted at

前書き

筆者は、競技プログラミング低レートなので、ご指摘などあればぜひよろしくお願いいたします!また、筆者のレベルが上がり次第この記事も更新していくつもりです。

bitとは

普段生活では10進数で物事を考えますが、PCの世界では基本0と1の二進数で計算されている(10進数:4 -> 2進数:11)ため、二進数でコードを書いた方がスッキリすることが多い(可読性は落ちるかもです)。特に全状態について処理しなければならない時、bit全探索は便利です。

bit操作とは

atcoderでbit操作を要求される場面は、ABCのE問題くらいまでは基本的な操作(and(&),or(|),xor(-),not(~),算術シフト(<<,>>))とbit全探索くらいなので、簡単にまとめます。

基本操作

and(&)

演算子(&)の左辺と右辺のビットを比較して、同じ位置のビットが両方1なら1にします。

int a = 2;   //10
int b = 3;   //11
int c = a & b;  //(10 & 11) = 10
System.out.print(c);  //2

or(|)

演算子(|)の左辺と右辺のビットを比較して、同じ位置のビットについて片方1なら1にします。

int a = 2;   //10
int b = 3;   //11
int c = a | b;  //(10 | 11) = 11
System.out.print(c);  //3

xor(^)

演算子(^)の左辺と右辺のビットを比較して、同じ位置のビットについて片方だけ1なら1にします。

int a = 2;   //10
int b = 3;   //11
int c = a ^ b;  //(10 ^ 11) = 01
System.out.print(c);  //1

not(~)

演算子(~)の右辺のビットを全部反転させます。

int a = 2;   //010
int c = ~a;  //(10 ^ 11) = 101
System.out.print(c);  //-3

notで表される2進数の数え方には注意が必要です。まず10進数を2進数に変換する時ですが、例えば10進数で8の時、2進数では1000です。しかし、これは正確に書くと01000になります。左端の数字は符号ビットといって、これが1だと負の数を表します。負の数の二進数の数え方はhttp://www.infonet.co.jp/ueyama/ip/binary/signedbin.htmlなどを参考にしてください。

シフト(<<,>>)

演算子の左辺について左(右)に右辺だけずらします。

int a = 2;   //10
int b = a << 1;  //(100) = 4
int c = a >> 1;  //(01) = 1

System.out.print(b);  //4
System.out.print(c);  //1

bit全探索

全状態を表して、各状態について処理をしたい時bitを使えば簡単にできる時があります。例えば人が5人いて、その中から何人か選んだ時、その中に20才以上の人が2人以上が含まれるのは?みたいな時、

解法

bit全探索を行い、立っているbitの数が2以上でかつそのbitの位置の人が20以上ならカウントする。

イメージ

bitは 00000 -> 00001 -> 00010 -> 00011 -> 00100
と遷移していく。例えば00010は1番目の人のみのグループを表しており、00101は0番目と2番目の人のグループを表している。

コード


static void solve(){

		int[] age = {12,14,20,4,24};
		int ans = 0;
		for(int bit = 0;bit < (1<<5);bit++){      //bit全探索=全状態について処理
			if(countbit(bit,5,age) >= 2){
				ans++;
			}
		}
		System.out.println(ans);     //8
	
       }

//立っているbitの数を数え、そのbitの位置の人が20才以上か見る。
static int countbit(int bit,int n,int[] age){						
		int count = 0;
		int x = 1;
		for(int i = 0;i < n;i++){
			if((x & bit) != 0 && age[i] >= 20){
				count++;
			}
			x <<= 1;
		}
		
		return count;
		
}

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?