<링크>
https://www.acmicpc.net/problem/5624
<풀이>
D앞의 수를 A,B,C라 하면
A+B+C=D 를 만족하면 D는 좋은 수이다.
같은 수를 여러번 더해도 된다. 수열의 수로 만들 수 있는 모든 조합을 세어보려면
1 2 3 5 7 10
1 + 1 + 1
1 + 1 + 2
1 + 1 + 3
,,,
10 + 10 + 10
일케 해야되는데 N^3이 걸린다. N이 5000이라 시간초과가 뜰 것이다.
A+B=D-C를 이용하면 된다.
D를 하나 찝어서 D의 앞의 수(C)를 다 빼본다.
그 후 A+B가 지금까지 나온적이 있었냐만 보면 된다.
A와 B는 AA가 돼도 되고 AB, BB가 되어도 되며 C가 섞여도 된다. 왜냐면 같은 수를 여러번 더해도 되기 때문이다. 그 말은 D의 앞에 있는 두 수로 만든 조합이면 뭐든 상관없다는 뜻이다.
예를들면)
1 2 3 4 5 6 7
D=6, C=1 // 6-1 = 5 -> 5를 6 앞의 어떤 두 수로 만들어도 상관없다. 1이 섞여도 된다.
5라는 조합이 나왔었는지 확인한 뒤, 있으면 정답을 늘려주고 바로 break를 해서 나와줘야 한다. 중복해서 셀 수 있기 때문이다.
6-1,6-2,6-3,6-4,6-5가 끝난 뒤에는
(D=7)도 똑같은 방식으로 확인해야하는데
그럼 현재의 (D=6)는 새로 올 (D=7)의 앞의 수가 되기 때문에
현재의 (D=6)으로 만들 수 있는 조합을 추가해줘야한다.
현재의 D=6일때
11,12,13,14,15
22,23,24,25
33,34,35
44,45
55 의 조합이 이미 체크되어있었으므로 확인 할 수 있었던 것이다.
6이 새로 추가됐을때
16,26,36,46,56,66 을 추가해줘야 다음번부터 체크할 수 있다.
따라서 맨앞부터 현재의D까지 생기는 조합을 새로 추가해준다.
처음에는 set으로 구현했다가 시간초과가 떴다.
set에서 있냐 없냐는 판단할 때 logN이 걸리는데 그럼 결국 N^2 * logN = 2억이 넘기 때문에 시간 초과가 뜬 것 같다.
메모리를 좀 빌려와서 배열에 체크하는 방식으로 바꾸니깐 통과되었다.
[D-C] 가 1이면 지금까지 나왔던 조합이라 생각한다.
이 때 D-C의 범위는 곧 A+B의 범위이고
-200000~200000이다.
그대로 오른쪽으로 20만 옮겨서 구현했다.
<소스코드>
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 | #include<set> #include<stdio.h> using namespace std; int a[5000]; int is[500000]; set<int> s; int main() { int N; int ans = 0; scanf("%d", &N); for (int i = 0; i < N; ++i) scanf("%d", a + i); for (int i = 0; i < N; ++i) { for (int j = 0; j < i; ++j) { int D_C = a[i] - a[j]; if (is[D_C+200000]) { ++ans; break; } } for (int j = 0; j <= i; ++j) is[a[i] + a[j] + 200000] = 1; } printf("%d", ans); } | cs |
'알고리즘 풀이 > 기타' 카테고리의 다른 글
백준 10973 이전 순열 (0) | 2018.07.24 |
---|---|
백준 10972 다음 순열 (1) | 2018.07.24 |
백준 2725 보이는 점의 개수:: 들짐승 (0) | 2018.07.22 |
백준 9011 순서 :: 들짐승 (1) | 2018.07.22 |
백준 8982 수족관1 :: 들짐승 (0) | 2018.07.22 |