https://www.acmicpc.net/problem/15990
방법 1: Top-down
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
import java.io.*;
import java.util.Scanner;
public class Main {
public static final long mod = 1000000009L;
public static long[][] arrResult;
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int iMax = 100000;
arrResult = new long[iMax + 1][4];
calculate(iMax);
int iTotalCase = sc.nextInt();
while (iTotalCase-- > 0) {
int temp = sc.nextInt();
bw.write(((arrResult[temp][1] + arrResult[temp][2] + arrResult[temp][3]) % mod)+"\n");
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static int calculate(int i) {
if (arrResult[i][1] > 0) {
return 0;
}
if (i <= 2) {
arrResult[0][1] = 1;
arrResult[1][1] = 1;
arrResult[2][2] = 1;
return 0;
}
calculate(i - 1);
arrResult[i][1] = (arrResult[i - 1][2] + arrResult[i - 1][3]) % mod;
arrResult[i][2] = (arrResult[i - 2][1] + arrResult[i - 2][3]) % mod;
arrResult[i][3] = (arrResult[i - 3][1] + arrResult[i - 3][2]) % mod;
return 0;
}
}
Colored by Color Scripter
|
방법 2: Bottom-up
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
Scanner sc = new Scanner(System.in);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int iMax = 100000;
int iMod = 1000000009;
int[] arrOne = new int[iMax + 1];
int[] arrTwo = new int[iMax + 1];
int[] arrThree = new int[iMax + 1];
int[] result = new int[iMax + 1];
arrOne[0] = 1;
arrOne[1] = 1;
result[1] = 1;
arrTwo[2] = 1;
result[2] = 1;
for (int i = 3; i <= iMax; i++) {
arrOne[i] = (arrTwo[i - 1] + arrThree[i - 1]) % iMod;
arrTwo[i] = (arrOne[i - 2] + arrThree[i - 2]) % iMod;
arrThree[i] = (arrOne[i - 3] + arrTwo[i - 3]) % iMod;
result[i] = ((arrOne[i] + arrTwo[i]) % iMod + arrThree[i]) % iMod;
}
int iTotalCase = sc.nextInt();
while (iTotalCase-- > 0) {
bw.write(result[sc.nextInt()]+"\n");
bw.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Colored by Color Scripter
|
c++소스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#include <iostream>
using namespace std;
const int DIV = 1000000009;
const int MAX = 100000;
int sum[MAX + 1][3 + 1];
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
/*
D[N][i] : N을 1, 2, 3의 합으로 나타내는 방법 중 i로 끝나는 경우의 수
점화식 : S[N] = D[N][1] + D[N][2] + D[N][3]
= D[N - 1][2] + D[N - 1][3]
+ D[N - 2][1] + D[N - 2][3]
+ D[N - 3][1] + D[N - 3][2]
*/
/*
케이스가 주어질 때마다 값을 구하는 것보다,
MAX만큼 미리 값을 구하고 케이스대로 출력하는 것이 시간효율적이다.
*/
sum[1][1] = 1;
sum[2][2] = 1;
sum[3][1] = 1;
sum[3][2] = 1;
sum[3][3] = 1;
for (int i = 4; i <= MAX; i++)
{
sum[i][1] = (sum[i - 1][2] + sum[i - 1][3]) % DIV;
sum[i][2] = (sum[i - 2][1] + sum[i - 2][3]) % DIV;
sum[i][3] = (sum[i - 3][1] + sum[i - 3][2]) % DIV;
}
int cnt;
cin >> cnt;
while (cnt--)
{
int n;
cin >> n;
cout << ((sum[n][1] + sum[n][2]) % DIV + sum[n][3]) % DIV << '\n';
}
return 0;
}
Colored by Color Scripter
|
바텀업이 더 효율적인 문제.
TIP1
타일링 문제와 비슷한 유형이다.
n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
단, 같은 수를 두 번 이상 연속해서 사용하면 안 된다.
N을 1, 2, 3의 합으로 나타내는 방법의 수를 D[N] 이라 하고,
마지막에 k를 더해주는 방법의 수를 A[N][k] 라 하자.
즉, D[N] = A[N][1] + A[N][2] + A[N][3] 이다.
타일링 문제를 떠올리며 식을 써보면 다음과 같다.
D[N] = D[N - 1] x 1을 더하는 방법
+ D[N - 2] x 2를 더하는 방법
+ D[N - 3] x 3을 더하는 방법
그런데 문제에서 같은 수를 두 번 이상 연속해서 쓸 수 없다고 했으므로,
1을 더하는 방법을 계산할때에는 D[N - 1] 이 아니라
D[N - 1] 에서 A[N - 1][1] 을 제외한 방법의 수.
즉, A[N - 1][2] + A[N - 1][3] 을 가져와야 한다.
그리고 k를 더하는 방법은 그냥 1 이므로
식을 다시 정리하면 다음과 같다.
D[N] = (A[N - 1][2] + A[N - 1][3])
+ (A[N - 2][1] + A[N - 2][3])
+ (A[N - 3][1] + A[N - 3][2])
TIP2
int 표현 범위의 한계가 약 20억이므로, 2개의 수를 더했다면 % 1000000009 를 연산해주자.
'Algorithm > BOJ' 카테고리의 다른 글
[BOJ]2193번: 이친수(java, c++) (0) | 2019.10.17 |
---|---|
[BOJ]10844번: 쉬운 계단 수(java, c++) (0) | 2019.10.15 |
[BOJ]16194번: 카드 구매하기 2(java, c++) (0) | 2019.10.15 |
[BOJ]11052번: 카드 구매하기(java, c++) (0) | 2019.10.14 |
[BOJ]9095번: 1, 2, 3 더하기(java, c++) (0) | 2019.10.14 |
댓글