문제: BOJ 24491 - Searching for Soulmates
소의 성격 수 \(A\)를 다른 소의 성격 수 \(B\)와 같게 만들기 위한 최소 연산 횟수를 구하는 문제입니다.
연산은 \(\times 2\), \(\div 2\)(짝수일 때만), \(+1\) 세 가지만 가능합니다.
문제 정보
문제 링크: https://www.acmicpc.net/problem/24491
문제 요약:
- \(N\)쌍의 소가 주어지고, 각 쌍마다 첫 번째 소의 성격 \(A\)를 두 번째 소의 성격 \(B\)로 바꿔야 한다.
- 연산: \(\times 2\), \(\div 2\)(\(A\)가 짝수일 때만), \(+1\).
- 각 쌍에 대해 필요한 최소 연산 횟수를 출력한다.
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 1024MB
- \(1 \le N \le 10\), \(1 \le A, B \le 10^{18}\)
입출력 예제
입력:
| |
출력:
| |
첫 번째 케이스: \(31 \to 32 \to 16 \to 8 \to 9 \to 10 \to 11 \to 12 \to 13\) (8번).
접근 방식
핵심 관찰 (USACO 공식 해설)
- 최적해 구조: 최적 연산 순서는 나눗셈만 → 덧셈만 → 곱셈만 세 단계로 나눌 수 있다. 즉, 곱셈 뒤에 나눗셈이 오는 경우는 최적이 아니다.
- 곱셈 횟수 \(M\) 고정: \(B\)의 하위 \(M\)비트를 “제거”한 값 \(\texttt{prefix} = B \gg M\)까지 \(A\)를 줄인 뒤, 덧셈으로 \(\texttt{prefix}\)에 맞추고, 곱셈 \(M\)번과 하위 비트만큼 \(+1\)로 \(B\)를 만든다.
- \(M\) 전수 시도: \(M = 0, 1, \ldots\) 에 대해 \(\texttt{prefix} = B \gg M > 0\)일 때만 비용을 계산하고, 그 중 최솟값이 답이다.
알고리즘 (요약)
- \(M\)(곱셈 횟수)을 0부터 올리면서:
- \(\texttt{prefix} = B \gg M\).
- \(A\)를 \(\texttt{prefix}\) 이하로 만들기: 홀수면 \(+1\) 후 \(\div 2\), 짝수면 \(\div 2\) 반복. 비용을 \(\texttt{here}\)에 누적.
- \(\texttt{here} \mathrel{+}= \texttt{prefix} - \texttt{cow}\) (덧셈으로 \(\texttt{prefix}\)까지).
- \(\texttt{here} \mathrel{+}= M\) (곱셈 횟수).
- \(\texttt{here} \mathrel{+}= \operatorname{popcount}(B \mathrel{\&} (2^M - 1))\) (하위 \(M\)비트에서 1인 만큼 \(+1\)).
- 위 비용 중 최솟값을 출력.
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(\log^2 \max(A,B))\) | \(M\)이 \(O(\log B)\)개, 각각 \(A\)를 줄이는 루프 \(O(\log A)\) |
| 공간 복잡도 | \(O(1)\) | 상수 개의 변수만 사용 |
구현 코드
C++
| |
Python
| |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| A = B | 이미 같음 | \(M=0\)에서 prefix=B, cow=A=B이면 here = 0 + 0 + 0 = 0 |
| A > B | 나눗셈으로만 줄여야 함 | 홀수면 +1 후 /2 반복으로 prefix 이하로 감 |
| A < B | 나눗셈 단계 후 덧셈·곱셈으로 B까지 | prefix - cow 와 하위 비트 popcount로 처리 |
| 큰 수 | \(A, B \le 10^{18}\) | C++은 long long, Python은 정수 그대로 사용 |
![Featured image of post [Algorithm] C++ / Python 백준 24491번: Searching for Soulmates](/post/algorithm/2026-03-10-boj-24491-searching-for-soulmates-cpp-python-solution/wordcloud_hu_5f8e0f6bff9a25f6.webp)
![[Algorithm] C++ / Python 백준 11238번: Fibo](/post/algorithm/2026-03-10-boj-11238-fibo-cpp-python-solution/wordcloud_hu_becd9f0d5bbc5cc4.webp)
![[Algorithm] C++ / Python 백준 24491번: Searching for Soulmates](/post/algorithm/2026-03-10-boj-24491-searching-for-soulmates-cpp-python-solution/wordcloud_hu_d731700bc50653bc.webp)
![[Algorithm] C++ / Python 백준 8927번: Squares](/post/algorithm/2026-03-10-boj-8927-squares-cpp-python-solution/wordcloud_hu_97ca55eeba6bb341.webp)
![[Algorithm] C++ 백준 12932번: 노래방](/post/algorithm/2026-02-24-boj-12932-karaoke/wordcloud_hu_1f0c8ee66631427c.webp)
![[Algorithm] C++ 백준 16879번: 궁전 게임](/post/algorithm/2026-02-23-boj-16879-palace-game-grundy-cpp-solution/wordcloud_hu_1c61cc44e16b2b69.webp)
![[Algorithm] C++/Python 백준 13926 gcd(n, k) = 1 — φ(n) 계산](/post/algorithm/2025-10-14-boj-13926-gcd-n-k-equals-1-cpp-python-solution/wordcloud_hu_7dd521dd47692e0.webp)
![[Algorithm] C++ 백준 17613번: 점프 - 구간 최대 점프넘버](/post/algorithm/2025-08-14-boj-17613-jump-range-maximum-jumpnumber-cpp-solution/wordcloud_hu_3a8e67c6892eb6d.webp)
![[Algorithm] C++ 백준 13013번: 접미사 배열 2](/post/algorithm/2026-02-05-boj-13013-suffix-array-2-min-distinct-characters-cpp-solution/wordcloud_hu_ee21aed3564c55d3.webp)