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

백준 1354번: 무한 수열 2

posite 2026. 4. 4. 14:10

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

 

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

  • Ai = 1 (i ≤ 0)
  • Ai = A⌊i/P⌋-X + A⌊i/Q⌋-Y (i ≥ 1)

1351번 무한 수열과 동일하게 방문한 값을 재방문하지 않게 하기 위해 Map<Long, Long>을 이용하여 재방문 시 저장한 값을 반환하는 백트래킹으로 풀이하였다.

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

 

 

위의 방식대로 796176 kb의 메모리와 4836ms가 소요되었다. 이를 더 최적화하기 위해 자주 호출되는 작은 값들은 더 빠른 배열에 저장하고 큰 값들만 Map에 저장하여 시간과 메모리를 모두 단축할 수 있다. 메모리 제한에 맞추어 10000000의 long[] 을 선언하고 100000000 이상의 값은 Map에 저장하였다.

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 무한수열1354 {
    
    private static final int MAX_CACHE = 10000000;
    private static long[] arrayCache = new long[MAX_CACHE];
    private static Map<Long, Long> mapCache = new HashMap<>();
    
    private static long n, p, q, x, y;
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        n = Long.parseLong(st.nextToken());
        p = Long.parseLong(st.nextToken());
        q = Long.parseLong(st.nextToken());
        x = Long.parseLong(st.nextToken());
        y = Long.parseLong(st.nextToken());
        
        System.out.print(solve(n));
    }
    
    private static long solve(long current) {
        if (current <= 0) {
            return 1;
        }
        
        if (current < MAX_CACHE) {
            if (arrayCache[(int) current] != 0) {
                return arrayCache[(int) current];
            }
        } else {
            if (mapCache.containsKey(current)) {
                return mapCache.get(current);
            }
        }
        
        long result = solve(current / p - x) + solve(current / q - y);
        
        if (current < MAX_CACHE) {
            arrayCache[(int) current] = result;
        } else {
            mapCache.put(current, result);
        }
        
        return result;
    }
}

 

 

230984kb의 메모리와 1452ms가 소요되어 상당한 향상 효과를 얻었다.