문제 정보
- 문제:
https://www.acmicpc.net/problem/5051 - 제목: 피타고라스의 정리
- 요약:
1 ≤ a,b,c ≤ n−1,a ≤ b에서 \(a^2 + b^2 \equiv c^2 \pmod n\)를 만족하는 삼중쌍 개수를 출력합니다.n은 최대 500,000입니다. - 제한: 시간 1초, 메모리 128MB, 입력 하나
n (2 ≤ n ≤ 500000)
입출력 형식/예제
입력
| |
출력
| |
또는
입력
| |
출력
| |
접근 개요(아이디어 스케치)
- 핵심 아이디어는 제곱 나머지 분포를 이용한 합성입니다.
cntSq[r] = |{x ∈ [1..n−1] : x^2 ≡ r (mod n)}|.A = cntSq라 두고,A ⊛ A의 순환 컨볼루션은 \((a^2 \bmod n) + (b^2 \bmod n)\)의 분포를 줍니다.
- 순서가 있는 (a,b) 쌍의 총 개수:
ordered = Σ_r (A ⊛ A)[r] · A[r](여기서r = c^2 mod n). a=b인 대각선 개수:equal = Σ_r A[r] · A[(2r) mod n].- 우리가 원하는
a ≤ b개수는 대칭 보정으로 \(\frac{ordered + equal}{2}\) 입니다. - 순환 컨볼루션은 FFT로 선형 컨볼루션을 계산한 뒤 길이
n에서 접기(folding)로 구현합니다:circ[k] = conv[k] + conv[k+n].
flowchart TD A[제곱 나머지 분포 A[r]] --> B[선형 컨볼루션 A*A (FFT)] B --> C[길이 n에서 접기(순환 컨볼루션)] C --> D[ordered = Σ_r circ[r]·A[r]] A --> E[equal = Σ_r A[r]·A[2r mod n]] D --> F[정답 = (ordered + equal)/2] E --> F
알고리즘 설계
cntSq를 선형 시간에 구성:x=1..n-1에 대해r=(x*x) mod n,cntSq[r]++.- 길이
L=2^k ≥ 2n로 zero-padding 하여 FFT 기반 선형 컨볼루션conv=A*A계산. - 순환 컨볼루션 복원:
circ[k] = conv[k] + conv[k+n] (0 ≤ k < n). ordered = Σ_k circ[k]·A[k],equal = Σ_r A[r]·A[(2r) mod n].answer = (ordered + equal)/2를 128비트 누적으로 출력.
올바름 근거(요지):
A⊛A는 \((a^2 mod n)+(b^2 mod n)\)의 분포를 정확히 세며,c선택은 같은 나머지r의 개수A[r]만큼 독립 곱으로 곱해집니다.- 순서쌍(ordered)에서
a≠b는 쌍대가 존재하므로 2배,a=b는 1배이므로a≤b변환식U=(O+E)/2가 성립합니다.
복잡도
- 시간: \(O(n \log n)\) (FFT 2회 + 역변환 1회)
- 공간: \(O(n)\)
구현 (C++)
| |
코너 케이스 체크리스트
- 작은 n (예: 2, 3, 4, 5, 6, 7)에서 직접 검증값과 비교
a=b대각선 보정:equal = Σ_r A[r]·A[2r mod n]식을 별도 확인- 부동소수점 반올림:
llround사용 및 음수 소수 에러 가드(max(·,0)) 적용 - 누적 오버플로: 합산은
__int128사용, 출력 시 자리수 단위 변환
제출 전 점검
- 입력/출력 형식 및 개행 확인
- FFT 길이
L은 항상2n이상인 2의 거듭제곱인지 확인 - 순환 컨볼루션 접기(
conv[k] + conv[k+n]) 구현 확인 - 시간/메모리 여유:
n=5e5에서도 길이≈1,048,576FFT 3회 내 처리
참고자료
- 순환 컨볼루션과 접기: 선형 컨볼루션 결과를 길이
n에서 접어 합산 - 대칭 보정:
U = (O + E) / 2(ordered→a≤b변환)
![Featured image of post [Algorithm] C++ 백준 5051번: 피타고라스의 정리 (mod n)](/post/algorithm/2025-10-14-boj-5051-pythagorean-mod-n-cpp-solution/wordcloud_hu_2a3aaf275fc43fb1.png)
![[Algorithm] C++ 백준 1031번: 스타 대결](/post/algorithm/2025-10-14-boj-1031-star-battle-cpp-solution/wordcloud_hu_f77f5f84ec32b33a.png)
![[Algorithm] C++ 백준 22289번: 큰 수 곱셈 (3)](/post/algorithm/2025-10-14-boj-22289-big-integer-multiplication-cpp-solution/wordcloud_hu_58aa21e0c6a28f67.png)
![[Algorithm] C++ 백준 5051번: 피타고라스의 정리 (mod n)](/post/algorithm/2025-10-14-boj-5051-pythagorean-mod-n-cpp-solution/wordcloud_hu_7e8a5079e9226a49.png)
![[Algorithm] C++ 백준 8464번: Non-Squarefree Numbers](/post/algorithm/2025-10-14-boj-8464-non-squarefree-numbers-cpp-solution/wordcloud_hu_4f80697d0be61606.png)
![[Algorithm] cpp 백준 12728번: n제곱 계산](/post/algorithm/2025-09-16-boj-12728-n-power-calculation-last-three-digits-cpp-solution/wordcloud_hu_767610d37d930d0a.png)
![[Algorithm] cpp 백준 17134번: 르모앙의 추측](/post/algorithm/2025-08-14-boj-17134-lemoine-conjecture-fft-convolution/wordcloud_hu_537c64ece4c0888d.png)
![[Algorithm] cpp 백준 15576번: 큰 수 곱셈 (2)](/post/algorithm/2025-09-16-boj-15576-big-integer-multiplication-2-cpp-solution/wordcloud_hu_dbfe394c17d3dbe8.png)
![[Algorithm] cpp 백준 11385번: 씽크스몰 - NTT+CRT 다항식 곱셈](/post/algorithm/2025-08-14-boj-11385-thinksmall-ntt-crt-cpp-solution/wordcloud_hu_ff091f7038a8767d.png)