\(n\)이 최대 \(2 \times 10^9\)이라서 실수 거듭제곱을 직접 계산할 수 없다.
대신 \((3+\sqrt5)^n\)과 켤레인 \((3-\sqrt5)^n\)를 함께 다루면 정수 점화식이 생기고, 이를 행렬 거듭제곱으로 \(O(\log n)\)에 풀 수 있다.
문제 정보
문제 링크: https://www.acmicpc.net/problem/12925
문제 요약:
- 각 테스트케이스마다 자연수 \(n\)이 주어진다.
- \((3+\sqrt5)^n\)의 정수부(floor)의 마지막 3자리를 구한다.
- 3자리가 안 되면 leading zero를 붙인다. (
027등)
제한 조건:
- 시간 제한: 2초
- 메모리 제한: 512MB
- \(1 \le T \le 100\)
- \(2 \le n \le 2 \times 10^9\)
입출력 예제
입력 1:
| |
출력 1:
| |
접근 방식
핵심 관찰 1: 켤레를 더하면 정수가 된다
\[ x = 3+\sqrt5,\quad y = 3-\sqrt5 \]를 두고,
\[ a_n = x^n + y^n \]을 정의하자. \(x, y\)는 켤레이므로 전개 시 무리수 항이 소거되어 \(a_n\)은 정수가 된다.
또한 \(0 < y < 1\) 이므로 \(n \ge 1\)에서 \(0 < y^n < 1\). 따라서
\[ x^n = a_n - y^n,\quad 0 < y^n < 1 \Rightarrow \lfloor x^n \rfloor = a_n - 1 \]즉, 우리가 구할 값은
\[ \lfloor (3+\sqrt5)^n \rfloor \bmod 1000 = (a_n - 1) \bmod 1000 \]이다.
핵심 관찰 2: \(a_n\)은 2차 선형 점화식을 따른다
\(x, y\)는 다음 방정식의 해다.
\[ t^2 - 6t + 4 = 0 \]따라서 \(x^2 = 6x - 4\), \(y^2 = 6y - 4\)이고, 양변에 \(x^{n-2}\), \(y^{n-2}\)를 곱해 더하면
\[ a_n = 6a_{n-1} - 4a_{n-2} \]초기값은
\[ a_0 = x^0 + y^0 = 2,\quad a_1 = x + y = 6 \]이다.
알고리즘 설계 (Mermaid Flowchart)
flowchart TD
A["입력: T"] --> B["각 테스트케이스 입력 n"]
B --> C["점화식 준비: a_n = 6 a_{n-1} - 4 a_{n-2}"]
C --> D["행렬 M = (6,-4; 1,0) 구성 (mod 1000)"]
D --> E["P = M^(n-1) 빠른 거듭제곱"]
E --> F["a_n = P00*a1 + P01*a0 (mod 1000)"]
F --> G["ans = (a_n - 1) mod 1000"]
G --> H["Case #c: ans를 3자리(leading zero)로 출력"]
복잡도 분석
| 항목 | 복잡도 | 비고 |
|---|---|---|
| 시간 복잡도 | \(O(T \log n)\) | 테스트케이스마다 2x2 행렬 거듭제곱 |
| 공간 복잡도 | \(O(1)\) | 상수 크기 행렬만 사용 |
코너 케이스 및 실수 포인트
| 케이스 | 설명 | 처리 방법 |
|---|---|---|
| leading zero | 3자리가 안 되면 027처럼 출력 | setw(3) + setfill('0') |
| 음수 계수(-4) | 모듈러 연산에서 음수 처리 실수 | 곱셈/덧셈 후 ((x%1000)+1000)%1000 |
| 큰 n (2e9) | 선형 반복은 불가능 | 행렬 빠른 거듭제곱 사용 |
| 정수부 변환 | \(\lfloor x^n \rfloor = a_n - 1\) 증명 누락 | \(0 |
구현 코드 (C++)
| |
![Featured image of post [Algorithm] C++ 백준 12925번: Numbers](/post/algorithm/2026-01-30-boj-12925-numbers-matrix-exponentiation-cpp-solution/wordcloud_hu_a25492d4747fefac.webp)
![[Algorithm] C++ 백준 19646번: Random Generator](/post/algorithm/2026-02-05-boj-19646-random-generator-fenwick-tree-order-statistics-cpp-solution/wordcloud_hu_800373ebf55b3405.webp)
![[Algorithm] C++ 백준 6194번: Building the Moat](/post/algorithm/2026-02-05-boj-6194-building-the-moat-convex-hull-cpp-solution/wordcloud_hu_cd20e7c2564c046e.webp)
![[Algorithm] C++ 백준 12925번: Numbers](/post/algorithm/2026-01-30-boj-12925-numbers-matrix-exponentiation-cpp-solution/wordcloud_hu_c254298302da6b9f.webp)
![[Algorithm] C++ 백준 13055번: K-Inversions](/post/algorithm/2026-01-30-boj-13055-k-inversions-fft-convolution-cpp-solution/wordcloud_hu_10e054e13f06bae9.webp)
![[Algorithm] C++ 백준 15517번: Array Manipulation at Moloco (Hard)](/post/algorithm/2026-01-30-boj-15517-array-manipulation-at-moloco-hard-fenwick-cpp-solution/wordcloud_hu_d7f8ddbe049ead8e.webp)
![[Algorithm] C++ 백준 11385번: 씽크스몰 - NTT+CRT 다항식 곱셈](/post/algorithm/2025-08-14-boj-11385-thinksmall-ntt-crt-cpp-solution/wordcloud_hu_5e4df8779ed3a52a.webp)
![[Algorithm] C++ 백준 14853번: 동전 던지기](/post/algorithm/2025-12-19-boj-14853-coin-tossing-cpp-solution/wordcloud_hu_969d47d88d4ed5d7.webp)
![[Algorithm] C++ 백준 3948번: 홍준이의 친위대](/post/algorithm/2025-12-19-boj-3948-hongjuns-royal-guards-cpp-solution/wordcloud_hu_ae566acf44915e67.webp)
![[Algorithm] C++ 백준 13618번: RSA](/post/algorithm/2025-12-12-boj-13618-rsa-cpp-solution/wordcloud_hu_616dee2e9286c63b.webp)
![[Algorithm] C++ 백준 2709번: 가장 작은 K](/post/algorithm/2025-12-08-boj-2709-smallest-k-last-digits-1-2-cpp-solution/wordcloud_hu_9737a176fd48c4c9.webp)