백준 2526번 싸이클 문제를 풀며 나머지 연산의 순환 특성을 이해하고 최적화하는 과정
두 정수 N과 P가 주어질 때, N을 계속 곱해가며 P로 나눈 나머지가 순환하는 구간의 길이를 구하는 문제입니다.
예를 들어 N=22, P=7일 때:
이렇게 1이 계속 반복되므로 사이클 길이는 1입니다.
처음에는 Deque를 사용해서 나머지들을 저장하고, 중복이 발견되면 사이클을 찾는 방식으로 접근했습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
// 입력 받기
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int P = Integer.parseInt(st.nextToken());
Deque<Integer> deque = new ArrayDeque<>();
int baseNum = N;
int devideNum = P;
while (true) {
baseNum = baseNum * N;
int namu = baseNum % devideNum;
baseNum %= devideNum;
if(deque.contains(namu)) {
deque.push(namu);
break;
}
deque.push(namu);
}
while (!deque.getFirst().equals(deque.getLast())) {
// System.out.println("getFirst(): "+deque.getFirst()+", getLast(): "+deque.getLast());// System.out.println("getFirst(): "+deque.getFirst()+", getLast(): "+deque.getLast());
deque.pollLast();
}
System.out.println(deque.size()-1);
}
}
GPT의 도움을 받아 더 효율적인 방법을 배웠습니다. 핵심은 나머지의 첫 등장 위치를 기록하는 것입니다.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int P = Integer.parseInt(st.nextToken());
int[] first = new int[P]; // 나머지의 첫 등장 위치
Arrays.fill(first, -1);
int x = N % P; // 나머지(0..P-1) 상태 위에서 시작
int idx = 0;
while (first[x] == -1) { // 처음 보는 나머지면 위치 기록
first[x] = idx++;
x = (x * N) % P; // 다음 항
}
int cycleLen = idx - first[x]; // 현재 x가 처음 나온 곳부터가 사이클
System.out.println(cycleLen);
}
}
복잡한 자료구조 사용
contains()는 O(n) 시간 복잡도사이클 경계 판단이 불명확
큰 수 처리 불필요
baseNum = baseNum * N 처럼 키우고 나중에 나머지 연산하는 대신시간 복잡도 O(P)
공간 복잡도 O(P)
명확한 로직
idx - first[x]로 사이클 길이 즉시 확정67 % 31 = 5
(5 x 67) % 31 = 25
(25 x 67) % 31 = 1
(1 x 67) % 31 = 5 // 5가 재등장!
22 % 7 = 1
(1 x 22) % 7 = 1 // 1이 바로 재등장!
이 문제의 핵심은 "다음 항 = (이전 항 x N) mod P" 인 유한 상태(0..P-1) 순환 수열이라는 점입니다.
문제의 본질 파악이 중요
적절한 자료구조 선택
코드 단순화의 가치
overflow-x: hidden으로 덮어둔 문제가 터지기까지. 테이블 오버플로부터 Radix Sheet 스크롤 잠금까지, 모바일 가로 스크롤 문제를 근본적으로 해결한 과정을 정리합니다.
Spring의 @Controller와 @RestController 어노테이션의 차이점과 사용 시나리오를 실제 예제와 함께 알아봅니다
Docker에서 Kubernetes로, 컨테이너 오케스트레이션의 세계로 들어가는 체계적인 학습 가이드 시리즈 소개
Kubernetes의 기본 개념을 이해하고, 첫 애플리케이션을 배포하며, kubectl 명령어를 마스터하는 실전 가이드