문제 링크
주의사항
- JAVA를 사용하여 프로그램을 사용하였습니다.
- 백준에서 코드를 작성하였을 때 아래 형태에서 Main에서 결과가 출력되어야 합니다.
public class Main{
public static void main(String[] args){
}
}
문제 설명
접근 방법
이 문제에 핵심
1. 기본으로 사용할 막대는 N개가 있으며, 각각 길이가 다릅니다.
2. 각 막대를 길이를 양의 정수 k을 설정해서 늘릴 수 있습니다.
3. Q개의 주어진 길이가 존재할 때 막대들을 해당 길이로 만들 수 있는 방법을 결과로 출력합니다.
알고리즘 진행 순서.
1. 입력된 정보를 저장합니다.
2. DP을 통해서 중복되는 연산을 최소화하여 각 길이를 막대로 만드는 방법을 탐색합니다.
3. 탐색을 통해 얻은 방법의 개수를 결과로 출력합니다.
막대 길이 구하기
기본 막대의 길이는 항상 늘리지 않고 만들 수 있는 길이입니다.
즉, 기본 막대기의 길이는 항상 만들 수 있기 때문에 방법의 값이 기본 1 이상입니다.
이후, 기본 막대기를 늘려서 만드는 방법에 대해서 알아보자.
만약, 기본 막대기의 길이가 2일 때
늘려서 만들 수 있는 길이 : 4, 6, 8, 10, 12
기본 막대기가 3일 때
늘려서 만들 수 있는 길이 : 6, 9, 12, 18
중요한 것은 방법의 개수를 구하는 것이므로써 기존의 6을 만들 수 있는 방법의 수가 3개이면 다음 배수들을 만들 수 있는 경우는 모두 +3을 해주어야 합니다.
Why?
6을 시작으로 파생되는 배수이기 때문에, ( 2 X 3, 3 X 2, 6)이면 파생되는 배수는
2 X 3 X 2
2 X 3 X 3
...
3 X 2 X 2
3 X 2 X 3
...
6 X 2
6 X 3
...
위처럼 진행되기 떄문에, 배수의 시작되는 방법 개수를 순차적으로 더해주면 됩니다.
※예제 입력을 푸는 과정을 확인하시면 이해하기 편하실 것입니다.
예제입력 1.
1. 입력된 정보를 저장합니다.
N : 5
1 | 2 | 3 | 4 | 5 |
Q : 6
1 | 2 | 3 | 4 | 5 | 6 |
2. DP을 통해서 중복되는 연산을 최소화하여 각 길이를 막대로 만드는 방법을 탐색합니다.
원래는 길이의 최대값 100,000까지 구해야 하지만, 편의상 10까지 구하겠습니다.
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
기본 막대기 설정
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
1의 배수일 때
1을 만들 수 있는 방법의 수 : 1개
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 |
2의 배수일 때
2을 만들 수 있는 방법의 수 : 2개
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 4 | 2 | 3 | 1 | 3 | 1 | 3 |
3의 배수일 때
3을 만들 수 있는 방법의 수 : 2개
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 4 | 2 | 5 | 1 | 3 | 3 | 3 |
4의 배수일 때
4을 만들 수 있는 방법의 수 : 4개
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 4 | 2 | 5 | 1 | 7 | 3 | 3 |
....
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 4 | 2 | 5 | 1 | 7 | 3 | 5 |
3. 탐색을 통해 얻은 방법의 개수를 결과로 출력합니다.
Q개의 구해야 하는 길이 : {1, 2, 3, 4, 5, 6}
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 2 | 2 | 4 | 2 | 5 | 1 | 7 | 3 | 5 |
- BufferedReader를 사용하여 입력되는 정보를 저장합니다.
- StringTokenizer를 이용하여 막대의 정보를 띄어쓰기 기준 나누었습니다.
- 점화식을 통한 각 길이에 따른 막대 만드는 방법의 개수를 탐색합니다.
- 각 목표 길이에 맞는 방법의 개수를 Bufferedwriter 저장합니다.
- BufferedWriter에 저장된 결과를 출력합니다.
결과코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
//입력값 처리하는 BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//결과값 출력하는 BufferedWriter
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int N = Integer.parseInt(br.readLine());
//막대 길이에 따른 방법 저장할 배열
int[] DP = new int[1000001];
//기본 막대기 정보 저장 배열
int[] basicStick = new int[N];
StringTokenizer st = new StringTokenizer(br.readLine()," ");
//기본 막대기 정보 저장
for(int i=0;i<N;i++){
basicStick[i] = Integer.parseInt(st.nextToken());
DP[basicStick[i]] = 1;
}
//길이에 따른 막대 만들 수 있는 방법 구하기
for(int i=1;i<=50000;i++){
for(int j=2;i*j <=100000;j++){
DP[i*j] = DP[i*j] + DP[i];
}
}
//만들어야 하는 막대의 길이 입력
int Q = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine(), " ");
//입력받아야 하는 길이에 따른 방법 개수 BufferedWriter 저장
for(int i=0;i<Q;i++){
int idx = Integer.parseInt(st.nextToken());
bw.write(String.valueOf(DP[idx]));
bw.write(" ");
}
bw.flush(); //결과 출력
bw.close();
br.close();
}
}
'백준' 카테고리의 다른 글
[백준, Java] 1527번, 금민수의 개수, (백트래킹) (0) | 2024.04.08 |
---|---|
[백준, Java] 24954번, 물약 구매, (백트래킹) (0) | 2024.04.02 |
[백준, Java] 1184번, 귀농, (누적합) (0) | 2024.03.20 |
[백준, Java] 14224번, 작은 정사각형2, (이분 탐색) (0) | 2024.03.14 |
[백준, Java] 2613번, 숫자구슬, (이분 탐색) (4) | 2024.03.05 |
댓글