Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

경쟁 프로그래밍과 코딩 테스트를 위한 C++ 핵심 트릭 총정리

경쟁 프로그래밍이나 코딩 테스트에서는 문제를 정확하고 빠르게 푸는 능력만큼이나 코드를 짧은 시간 안에 작성하는 능력도 중요합니다. 이 글에서는 작성 시간을 줄이고 코드 효율을 높여 주는 실용적인 C++ 트릭들을 하나씩 소개합니다.

1. % 연산자 없이 홀수·짝수 판별하기

비트 AND 연산(&)을 활용하면 나머지 연산자 없이도 홀짝을 판별할 수 있습니다. 모든 홀수는 최하위 비트(LSb)가 1이므로, 숫자와 1을 AND 연산한 결과가 0이 아니면 홀수, 0이면 짝수입니다.

if ((n & 1) != 0) {
    // 홀수
} else {
    // 짝수
}

2. 시프트 연산자로 곱셈·나눗셈 빠르게 처리하기

어떤 수를 2의 n제곱으로 곱할 때는 왼쪽 시프트(<<)를 n번, 나눌 때는 오른쪽 시프트(>>)를 n번 하면 됩니다. 곱셈·나눗셈보다 훨씬 빠르게 동작합니다.

x = 40;
y = x << 2; // x * 4 = 160
x = 40;
y = x >> 2; // x / 4 = 10

3. 임시 변수 없이 두 변수 값 교환하기

+와 - 연산자를 사용해도 되지만, XOR 연산자(^)를 이용하면 더 간결하게 교환할 수 있습니다.

// x와 y 교환
x ^= y;
y ^= x;
x ^= y;

4. strlen() 없이 문자열 순회하기

문자열의 각 문자에 접근하는 것이 목적이라면 굳이 strlen() 함수가 필요하지 않습니다. 해당 위치의 문자가 널 문자(0)인지 검사하여 유효한 동안만 반복하면 됩니다.

for (int i = 0; s[i]; i++) {
    cout << s[i];
}

5. push_back() 대신 emplace_back() 사용하기

vector 같은 STL 컨테이너에 요소를 추가할 때 emplace_back()을 사용하면 더 빠릅니다. 이 함수는 별도의 메모리를 새로 할당해 복사하는 대신, 컨테이너 내부에서 직접 객체를 생성하기 때문입니다.

6. 내장 GCD 함수 활용하기

C++에는 최대공약수(GCD)를 구하는 내장 함수가 제공됩니다. 직접 유클리드 호제법을 구현할 필요 없이 아래처럼 바로 사용할 수 있습니다.

__gcd(x, y) // x와 y의 최대공약수

7. 배열 크기 선언 팁

main 함수 안에서 선언하는 지역 배열은 스택 크기 제한 때문에 약 10^6 수준이 한계입니다. 반면 전역(global)으로 선언하면 최대 10^7까지 확보할 수 있으므로, 큰 배열이 필요하면 전역으로 선언하는 것이 좋습니다.

8. 로그 연산으로 최상위 자릿수 구하기

log10을 활용하면 어떤 수의 가장 앞자리 숫자도 손쉽게 계산할 수 있습니다.

n = 4578;
double k = log10(n);
k = k - floor(k);
int x = pow(10, k); // x는 최상위 자릿수

9. 로그 연산으로 자릿수 개수 구하기

반복문 없이 log10 함수만으로 자릿수를 바로 구할 수 있습니다.

n = 4578;
int digit_count = floor(log10(n)) + 1;

10. 2의 거듭제곱 여부 확인하기

x와 (x-1)을 AND 연산했을 때 결과가 0이면 x는 2의 거듭제곱입니다. 예를 들어 1024(2^10)는 이 조건을 만족합니다.

x = 1024;
bool check = x && (!(x & (x - 1))); // true이면 2의 거듭제곱

11. all_of, any_of, none_of 알고리즘

C++ STL에는 조건을 일괄 검사하는 유용한 알고리즘이 내장되어 있습니다.

all_of(left, left + n, isPositive());  // 모든 원소가 양수인지 검사
any_of(left, left + n, isPositive());  // 하나라도 양수가 있는지 검사
none_of(left, left + n, isPositive()); // 양수가 하나도 없는지 검사

12. copy_n으로 컨테이너 복사하기

copy_n 함수를 사용하면 한 컨테이너의 요소를 다른 컨테이너로 간단히 복사할 수 있습니다.

int src[5] = {10, 20, 30, 40, 50};
int dest[5];
copy_n(src, 5, dest);

13. itoa로 연속된 값 생성하기

itoa 알고리즘은 시작 값을 첫 요소에 저장한 뒤, 후위 증가 연산자를 적용하듯 연속적으로 증가하는 값들의 범위를 만들어 줍니다.

int arr[5] = {0};
char str[5] = {0};
iota(arr, arr + 5, 15);   // {15, 16, 17, 18, 19} 생성
iota(str, str + 5, 'A');  // {'A', 'B', 'C', 'D', 'E'} 생성

14. 2진수 리터럴로 값 할당하기

C++14부터는 0b 접두사를 붙여 2진수 형태 그대로 값을 표현할 수 있습니다.

int x = 0b1101; // x에는 13이 저장됨

15. 조건 연산자 대신 키워드 사용하기

C++에서는 &&, || 같은 기호 대신 'and', 'or' 같은 키워드를 사용할 수도 있습니다. 가독성이 좋아지는 장점이 있습니다.

x = 10;
if (x < 20 and x > 5)
    cout << "True" << endl;
else
    cout << "False" << endl;
// 결과: True 출력

이 외에도 경쟁 프로그래밍에서는 매크로 축약, fast IO(cin/cout 동기화 해제), 디버깅용 assert 활용 등 다양한 기법들이 함께 사용됩니다. 위 트릭들을 익혀 두면 불필요한 코드 작성 시간을 줄이고, 남은 시간을 문제 해결 자체에 집중할 수 있습니다.