728x90
https://www.acmicpc.net/problem/2487
2487번: 섞기 수열
A1, A2, …, AN으로 표시된 N 개의 카드를 정해진 방법으로 섞고자 한다. 그 섞는 방법은 1에서 N까지의 숫자로 이루어진 수열로 표시된다. 이 수열을 섞기 수열이라 하자. 섞기는 현재 가지고 있는
www.acmicpc.net
728x90
메모리: 16,688 KB , 시간: 184 ms
사용 알고리즘: 순열 사이클 분할, 유클리드 호제법
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Iterator;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// N := 카드의 수
int N = Integer.parseInt(br.readLine());
// 섞기 수열 입력
int[] arr = new int[N + 1];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 1; i <= N; i++) {
arr[Integer.parseInt(st.nextToken())] = i; // 현재 자리에서 다음으로 갈 곳 저장
}
// 각 자리별로 원래 자리에 돌아오려면 최소 몇 번 루트를 돌아야 하는지 구하기
boolean[] visited = new boolean[N + 1]; // 이미 구한 곳은 구하지 않음
HashSet<Integer> set = new HashSet<>(); // 각 자리별 궤적을 저장하기 위한 set
for (int i = 1; i <= N; i++) {
if(visited[i]) continue;
int now = arr[i]; // 한 번 섞었을 때의 위치
int count = 1; // 최소 궤적 저장
visited[now] = true;
while(now != i) {
count++;
now = arr[now];
visited[now] = true;
}
set.add(count); // 최소 궤적 저장
}
// set에 있는 최소 궤적들을 하나씩 꺼내며 최소공배수 구하기
Iterator<Integer> iter = set.iterator();
long result = 1;
while(iter.hasNext()) {
result = getLcm(result, (long)iter.next());
}
System.out.println(result);
}
private static int getLcm(long a, long b) {
// 유클리드 호제법
// 1. 최대공약수 구하기
long gcd;
if(a > b) gcd = getGcd(a, b);
else gcd = getGcd(b, a);
// 2. 최대공배수 구하기
return (int)((a * b) / gcd);
}
private static long getGcd(long a, long b) {
if(a % b == 0) return b;
return getGcd(b, a % b);
}
}
728x90
'Problem Solving > BOJ' 카테고리의 다른 글
[백준, BOJ 1720] 타일 코드 (java) (1) | 2023.11.14 |
---|---|
[백준, BOJ 27653] 최소 트리 분할 (java) (1) | 2023.11.09 |
[백준, BOJ 14499] 주사위 굴리기 (java) (0) | 2023.11.06 |
[백준, BOJ 11265] 끝나지 않는 파티 (java) (1) | 2023.10.31 |
[백준, BOJ 1937] 욕심쟁이 판다 (java) (0) | 2023.10.26 |