\(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_95db1bff9791498f.png)
![[Algorithm] C++ 백준 12925번: Numbers](/post/algorithm/2026-01-30-boj-12925-numbers-matrix-exponentiation-cpp-solution/wordcloud_hu_3ddd9b1682d67718.png)
![[Algorithm] C++ 백준 13055번: K-Inversions](/post/algorithm/2026-01-30-boj-13055-k-inversions-fft-convolution-cpp-solution/wordcloud_hu_7e5ebc7c87d06324.png)
![[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_521deba1ba8bdbdd.png)
![[Algorithm] C++ 백준 14288번: 회사 문화 4](/post/algorithm/2026-01-24-boj-14288-company-culture-4-tree-queries-fenwick-cpp-solution/wordcloud_hu_71f27d76781ea5f9.png)
![[Algorithm] C++ 백준 24271번: xor²](/post/algorithm/2026-01-24-boj-24271-xor-squared-xor-permutation-segment-tree-cpp-solution/wordcloud_hu_26a096bd3c9cd391.png)
![[Algorithm] C++ 백준 12728번: n제곱 계산](/post/algorithm/2025-09-16-boj-12728-n-power-calculation-last-three-digits-cpp-solution/wordcloud_hu_17e1d3609f3d37a9.png)
![[Algorithm] C++ 백준 14289번: 본대 산책 3](/post/algorithm/2026-01-02-boj-14289-bondae-walk-3-matrix-exponentiation-cpp-solution/wordcloud_hu_dfec1c79bcd6ef2.png)
![[Algorithm] C++ 백준 22878번: 간단한 문제](/post/algorithm/2025-12-19-boj-22878-simple-problem-cpp-solution/wordcloud_hu_9d894140dc563b74.png)
![[Algorithm] C++ 백준 32190번: Ian Sequences](/post/algorithm/2025-12-19-boj-32190-ian-sequences-cpp-solution/wordcloud_hu_8da1eebaa2f85a3a.png)
![[Algorithm] C++ 백준 12850번 본대 산책2](/post/algorithm/2025-12-04-boj-12850-campus-walk-matrix-exponentiation-cpp-solution/wordcloud_hu_681273723a95d93a.png)