문제 요약 및 풀이
문제를 보자마자, 일단 쭉 나열해봤다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1 2
1 2
1 2 3
3 2 1
1 2 3 4
3 2 1 4
1 2 3 4 5
1 2 5 4 3
1 2 3 4 5 6
1 6 5 4 3 2
1 2 3 4 5 6 7
7 6 5 4 3 2 1
1 2 3 4 5 6 7 8
7 6 5 4 3 2 1 8
1 2 3 4 5 6 7 8 9
1 6 5 4 3 2 9 8 7
나열을 직접 해보면서 규칙성을 찾으려고 했는데, 두 가지를 발견했다.
- 무조건 2개의 숫자 혹은 같은 숫자끼리 짝 지으면 된다.
- 가장 큰 수 부터 가능한 가장 가까운 2의 거듭제곱 합을 만들면서 내려오면 된다는 것.
말 그대로 그리디하게 쭈욱 최적의 답을 넣으면서 오면 된다는 것이다.
풀이 코드
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
#include <bits/stdc++.h>
using namespace std;
int N;
int D[11000];
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> N;
for(int i = N; i > 0; i--) {
if(D[i]) continue;
int z = 2;
while(true) {
if(z > i && !D[z-i]) {
D[i] = z-i;
D[z-i] = i;
break;
}
z <<= 1;
}
}
for(int i = 1; i <= N; i++) {
cout << D[i] << "\n";
}
}
끝