알고리즘(백준 등) 공부/백준(자바)

백준 1351번: 무한 수열

posite 2026. 4. 2. 11:59

https://www.acmicpc.net/problem/1351

주어진 n, p, q이 주어질 때 다음의 조건을 만족하는 수열에 대해서 An을 구하는 문제이다. 0<= n <=10^12, 2<=p,q <=10^9

  • A0 = 1
  • Ai = A⌊i/P⌋ + A⌊i/Q⌋ (i ≥ 1)

처음에는 단순하게 백트래킹만으로 풀이하였다. 현재 n을 current/p 번째 항, current/q 번째 항으로 나누어 구한 후 더한 값을 반환하게 하였다.

private static long backtracking(long current) {
    if (current == 0) {
        return 1;
    }
    return backtracking(current / p) + backtracking(current / q);
}

 

 

그러나 current/p, current/q 가 같은 값을 가지게 되는 경우가 많아 많은 횟수를 반복하게 되고 시간 초과가 발생하였다. 그러므로 current/p, current/q가 이미 방문한 값을 재방문하지 않게 하기 위해 Map<Long, Long>을 이용하여 재방문 시 저장한 값을 반환하게 하여 해결하였다.

static Map<Long, Long> memo = new HashMap<>();

private static long backtracking(long current) {
    if (current == 0) {
        return 1;
    }
    if (memo.get(current) != null) {
        return memo.get(current);
    }
    
    long result = backtracking(current / p) + backtracking(current / q);
    memo.put(current, result);
    return result;
}

 

 

결과 코드는 다음과 같다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

public class 무한수열1351 {
    
    static long p, q;
    static Map<Long, Long> memo = new HashMap<>();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        long n = Long.parseLong(st.nextToken());
        p = Long.parseLong(st.nextToken());
        q = Long.parseLong(st.nextToken());
        br.close();
        System.out.print(backtracking(n));
    }
    
    private static long backtracking(long current) {
        if (current == 0) {
            return 1;
        }
        if (memo.get(current) != null) {
            return memo.get(current);
        }
        
        long result = backtracking(current / p) + backtracking(current / q);
        memo.put(current, result);
        return result;
    }
}