문제 정보
문제 링크: https://www.acmicpc.net/problem/2709
문제 요약: $R(1 \le R \le 20)$이 주어질 때, $2^k$의 마지막 $R$자리가 1과 2로만 이루어지는 가장 작은 $k$를 찾는다. $T(1 \le T \le 50)$개의 테스트 케이스를 각각 처리한다.
제한 조건:
- 시간 제한: 1초
- 메모리 제한: 128MB
- 입력 크기: $1 \le R \le 20$, $1 \le T \le 50$
입출력 예제
입력 1:
| |
출력 1:
| |
접근 방식
핵심 관찰
- $10^R = 2^R \cdot 5^R$이므로 모듈러를 두 부분으로 분리해 CRT로 재결합하면 큰 정수 없이 계산 가능하다.
- $2$의 법 $5^r$에서의 위수는 $4 \cdot 5^{r-1}$이다. 자리수를 한 자리 늘릴 때 주기가 5배 커지므로 이전 답 $k_{r-1}$에 대해 $k_r$는 $k_{r-1} + t \cdot \text{ord}_{r-1}$ (0 ≤ t < 5) 중 하나만 확인하면 된다.
- 각 후보 $k$마다 $2^k \bmod 2^r$, $2^k \bmod 5^r$를 빠른 거듭제곱으로 구한 뒤 CRT로 $2^k \bmod 10^r$를 복원하고, 하위 $R$자리가 모두 1 또는 2인지 검사한다.
알고리즘 설계 (Mermaid)
flowchart TD
A[입력 T] --> B[각 테스트 R 수집, 최대 Rmax 계산]
B --> C[ord[r]=4·5^(r-1) 전처리]
C --> D[기저: k[1]=1]
D --> E[r = 2..Rmax 반복]
E --> F[step = ord[r-1], base = k[r-1]]
F --> G{t = 0..4}
G --> H[후보 cand = base + step*t]
H --> I[mod2 = 2^cand mod 2^r]
I --> J[mod5 = 2^cand mod 5^r]
J --> K[CRT로 mod10 = 2^cand mod 10^r]
K --> L{하위 r자리가 1/2?}
L -- Yes --> M[k[r]=cand; break]
L -- No --> G
M --> N[모든 R 처리 후 질의별 k[R] 출력]
단계별 로직
- 전처리: $5^r$, $2^r$, 그리고 $2$의 법 $5^r$ 위수(순환 길이) $4 \cdot 5^{r-1}$을 $r=1..R_{\max}$까지 계산한다.
- 답 테이블 구성: $r=1$일 때 $k=1$. $r>1$에서는 이전 답 $k_{r-1}$을 기준으로 주기 크기만큼 5개 후보를 검사하며 처음으로 조건을 만족하는 $k_r$를 저장한다.
- CRT 복원: $x \equiv a \pmod{2^r}$, $x \equiv b \pmod{5^r}$을 역원을 이용해 하나의 $x < 10^r$로 합친다.
- 자리수 검사: $x$의 하위 $r$자리를 확인해 1 또는 2만 포함되는지 체크한다.
- 출력: 테스트 케이스별로 미리 구한 $k[r]$을 O(1)로 반환한다.
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | $O(R_{\max} \cdot 5 \cdot \log 5^R)$ | 각 자리 증가마다 후보 5개, 모듈러 거듭제곱 |
| 공간 복잡도 | $O(R_{\max})$ | $k$, $5^r$, $2^r$, 위수 테이블 |
구현 코드
C++
| |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| R=1 | 기저 사례 | $k_1=1$로 초기화 |
| 최대 R=20 | $5^{20}$ 크기와 오버플로 | __int128으로 곱셈/모듈러 계산 |
| 모듈러 역원 계산 | $2^r$와 $5^r$은 서로소 | 확장 유클리드로 역원 계산 |
| 후보 없음 | 이론상 항상 존재 | 5개 후보 모두 검사 |
| 입력 다수(T) | 중복 계산 방지 | $R_{\max}$까지 미리 DP 후 질의 응답 |
마무리
주기 확장 성질 덕분에 자리수를 한 칸 늘릴 때마다 단 5개 후보만 검사하면 되며, CRT로 10진 모듈러를 복원해 큰 정수 라이브러리 없이도 정확하게 답을 구할 수 있다.
![Featured image of post [Algorithm] C++ 백준 2709번: 가장 작은 K](/post/algorithm/2025-12-08-boj-2709-smallest-k-last-digits-1-2-cpp-solution/wordcloud_hu_bf41b32da7428580.png)
![[Algorithm] C++ 백준 17367번: 공교육 도박](/post/algorithm/2025-12-08-boj-17367-public-education-gambling-expectation-cpp-solution/wordcloud_hu_bdfe129f139e2d92.png)
![[Algorithm] C++ 백준 19693번: Safety](/post/algorithm/2025-12-08-boj-19693-safety-stacks-smooth-cpp-solution/wordcloud_hu_e00d069337dc3e1b.png)
![[Algorithm] C++ 백준 2709번: 가장 작은 K](/post/algorithm/2025-12-08-boj-2709-smallest-k-last-digits-1-2-cpp-solution/wordcloud_hu_2c72a969698601f4.png)
![[Algorithm] C++ 백준 123336번 A Sorting Problem - 역순쌍 개수](/post/algorithm/2025-12-04-boj-23336-sorting-problem-inversion-count-cpp-solution/wordcloud_hu_2ae546143d7768fd.png)
![[Algorithm] C++ 백준 12844번: XOR](/post/algorithm/2025-12-04-boj-12844-xor/wordcloud_hu_72acdccb71715643.png)
![[Algorithm] C++ 백준 12728번: n제곱 계산](/post/algorithm/2025-09-16-boj-12728-n-power-calculation-last-three-digits-cpp-solution/wordcloud_hu_767610d37d930d0a.png)
![[Algorithm] C++/Python 백준 10854번: Divisions - 약수 개수](/post/algorithm/2025-09-16-boj-10854-divisions-number-of-divisors-cpp-python-solution/wordcloud_hu_f2a53254f2f126b2.png)
![[Algorithm] C++ 백준 11385번: 씽크스몰 - NTT+CRT 다항식 곱셈](/post/algorithm/2025-08-14-boj-11385-thinksmall-ntt-crt-cpp-solution/wordcloud_hu_ff091f7038a8767d.png)
![[Algorithm] C++ 백준 8464번: Non-Squarefree Numbers](/post/algorithm/2025-10-14-boj-8464-non-squarefree-numbers-cpp-solution/wordcloud_hu_4f80697d0be61606.png)
![[Algorithm] C++ 백준 23575번: Squid Game](/post/algorithm/2025-12-04-boj-23575-squid-game-cpp-solution/wordcloud_hu_3623649df8b22837.png)