문제 : https://www.acmicpc.net/problem/2551
[ 알고리즘풀이 ]
N 이 5,000,000 이고 들어오는 숫자의 범위가 1 ~ 10000 이므로 모든 숫자 범위(1 ~ 10,000)에 대해5,000,000 개의 N을 전체 순회하며 값을 구하면 10,000 * 5,000,000 으로 시간 초과를 받게 된다.
시간 초과 문제를 해결하려면 N은 5백만으로 크지만 숫자 범위가 1부터 10,000으로 작다는 조건에 집중해야한다.
-1) 1 ~ 10,000까지 들어오는 Input 을 count 해주는 list 를 하나 선언해 Input을 받으면서 count 해준다. O(5,000,000) 만에 각각 숫자가 몇 개 있는지 count 를 할 수 있다.
-2) 어차피 대표 자연수는 1 ~ 10,000 을 벗어나지 않으므로 1 ~ 10,000 까지 모든 수들을 대표 자연수 후보로 보고 list를 순회하며 최소값을 갱신한다.
list 의 크기가 10,000 이고 대표 자연수 후보도 10,000 이므로 O(10^8) 만에 대표 자연수를 구할 수 있고, 대표자연수를 구하는 2가지 방법에 대해 각각 수행하므로 O(2 * 10 ^ 8) 의 복잡도로 2초 안에 문제를 해결할 수 있다.
#include<iostream>
#include<cmath>
using namespace std;
int list[10001] = {};
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int N, input;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> input;
list[input]++;
}
int ans1 = 1, ans2 = 1;
long long minSum1 = 999999999999999, minSum2 = 999999999999999, sum1, sum2;
for (int i = 1; i <= 10000; i++) {
sum1 = 0;
for (int j = 1; j <= 10000; j++) {
sum1 += 1LL * list[j] * abs(i - j);
}
if (sum1 < minSum1){
minSum1 = sum1;
ans1 = i;
}
}
for (int i = 1; i <= 10000; i++) {
sum2 = 0;
for (int j = 1; j <= 10000; j++) {
sum2 += 1LL * list[j] * (abs(i - j) * abs(i - j));
}
if (sum2 < minSum2) {
minSum2 = sum2;
ans2 = i;
}
}
cout << ans1 << ' ' << ans2;
}
'Problem Solving > BOJ' 카테고리의 다른 글
[BOJ] 2033 : 반올림 - travelbeeee (0) | 2020.01.21 |
---|---|
[BOJ] 15975 : 화살표 그리기 - travelbeeee (0) | 2020.01.21 |
[BOJ] 18245 : 이상한 나라의 암호 - travelbeeee (0) | 2020.01.17 |
[BOJ] 1919 : 애너그램 만들기 - travelbeeee (0) | 2020.01.16 |
[BOJ] 4641 : Doubles - travelbeeee (0) | 2020.01.03 |