출처: https://blog.naver.com/jhc9639/222310927725

 

1. Shift 연산 특징

a << b  =   a * (2^b)

a >> b  =   a / (2^b)

#include<iostream>

using namespace std;

int main(void) 
{
	// a << b  =  a * (2^b)
	int a = 5;
	int b = 2;
	// 5  *  (2 ^ 2 ) = 20
	cout << (a << b) << endl;
	cout << (a >> b); // 5  / (2^2) = 1;
}

 

2. Weird 연산자 특징

~ :  One's Complement  1의 보수 연산자(비트 반전), weird 연산자

 ~(value) = -(value + 1)

#include<iostream>

using namespace std;

int main(void) 
{
	// ~ :  One's Complement  1의 보수 연산자(비트 반전), weird 연산자
	// ~(value) = -(value + 1)
	
	
	/*
	000000011 (3)
	111111100 (~3)
	*/
	cout << ~3;  // -4
}

 

음수(-value) : 비트를 반전 한 수(~value) + 1

-value = ~value + 1

~value = -(value + 1)

-16은?

16 = 00010000 

11101111 + 1 = 11110000 (~16 + 1 = -16) 

 

~16 == -(16 + 1) = -17.

 + 1 

------

-16 ( -17 + 1)

#include<iostream>

using namespace std;

int main(void) 
{
	cout << ~16+1;  // -16
}

 

3. 활용 ( idx 번째 비트끄기)

암기

idx번째 비트끄기 S &= ~(1<<idx)
idx번째 비트 XOR 연산 S ^= (1<<idx)
최하위 켜져있는 비트 찾기 idx = (S & -S)
크기가 n인 집합의 모든 비트를 켜기 (1<<n) -1
idx번째 비트를 켜기 S |= (1 << idx)
idx번째 비트가 켜져 있는지 확인 if(S & ( 1<<idx))

 

 

4. 보수

https://yiyj1030.tistory.com/83

 

2의 보수란?? 쉬운 설명으로 궁금증 해결.. (비트 연산)

2의 보수: 컴퓨터가 음수를 저장하기 위해 사용하는 방법 중 하나. 예를 들어 4비트 머신을 생각해보자. 이 머신은 0000부터 1111부터 표현이 가능하다. 총 16개. 양수만을 저장하고싶다면 숫자 0부

yiyj1030.tistory.com

 


비트마스킹 

#1  경우의 수 (조합)

#include<iostream>

using namespace std;

/*
공간이 4개면 2^4 이 경우의 수
0000 (공집합)
0001  0 인덱스  사과
0010  1 idx  딸기
0011  0, 1 idx  사과/딸기
0100  2 idx  포도
0101  0, 2 idx   사과/포도
0110
0111
1000
1001
1010
1011
1100
1101
1110 1,2,3 idx 딸기/포도/배
1111  0~3  idx 사과/딸기/포도/배
*/
const int n = 4;
int main(void) 
{
	string a[n] = { "사과","딸기","포도","배" };
	for (int y = 0; y < (1 << n); ++y) {
		string ret = "";
		for (int x = 0; x < n; ++x) {
			if (y & (1 << x)) {  //  y가 0일때는 공집합.  1일때는 x가 0일때 if조건 성립(사과). y가 2일 때, x가 1일때 성립(딸기). y가 3일때 x는 0, 1 일때 성립(사과/딸기).
				ret += a[x] +" ";
			}
		}
		cout << ret << endl;
	}
}

#2 경우의 수 (조합)

visited를 대체하는 비트마스킹.

#include<iostream>

using namespace std;

const int n = 4;
string a[4] = { "사과","딸기","포도","배" };
void go(int num) {
	string ret = "";
	for (int x = 0; x < n; ++x) {
		if (num & (1 << x)) ret += a[x]  + " ";
	} 
	cout << ret << endl;  // 사과,딸기 / 사과,포도 / 사과,배
	return;
}
int main(void) {
	//visited 플래그 없이 합(bit)연산자로 출력.  사과의 짝.  
	for (int x = 1; x < n; ++x) {
		go(1 | (1 << x));
	}
	return 0;
}

비트마스킹의 한계는 n이 31까지(int형)

2^30승은 약 10억이 된다. 그 이후의 값들은 시간복잡도를 많이 초과하기에 비트마스킹은 보통 30~31까지 경우의 수만 표현가능.

 

문제에서 n <=30 이고 경우의 수를 구하는 문제면 비트마스킹으로 풀이가능.

+ Recent posts