https://www.acmicpc.net/problem/6986

 

6986번: 절사평균

첫째 줄에 절사평균(N, K)를, 둘째 줄에 보정평균(N, K)를 각각 소수점이하 셋째 자리에서 반올림하여 둘째 자리까지 출력한다. 예를 들어 결과값이 9.667인 경우 9.67로, 5인 경우 5.00으로, 5.5인 경우에는 5.50으로 출력한다.

www.acmicpc.net

문제 내용

 

2008년도 초등부 문제 풀어보다가 1번 문제라서 쉽겠거니 하고 했다가 우수수 하고 틀려버렸다 ㅡㅡ

 

문제 내용은 크게 어려운 것은 없다.

 

규칙에 맞게 절사평균과 보정 평균을 구해주면 되는데, 배열로 받은 뒤 소팅해서

 

앞에 k개 만큼을 날리던지, 근처 값으로 변경해주던지 하면 된다.

 

 

하 그놈의 Floating Point 정확도 문제

 

Floating Point precision 문제때문에 하....

 

 

일단 입력값 중 점수는 0 ~ 10범위의 실수에 소숫점 한자리까지 나오는 floating point이고

전채 개수가 10만개 까지 나올 수 있다.

 

10만개라는 이유 때문에 precision 문제가 발생할 수 있다.

컴퓨터에서 사용하는 부동소수점 방식은 작은 에러값이 발생할 수 있다.

따라서 이게 누적되면 정확하지 않은 값이 나올 수 있는데

 

 

따라서 정수로 환원해서 풀어야 한다.

 

 

결과값은 소수점 2자리까지 출력해야하고, 이로 인해서 100을 곱하면 되겠지만, 소수점 셋째자리에서

 

반올림을 해야 하므로 1000을 곱해서 소수점 셋째자리까지 일단 표현 가능하게 정수로 받았다.

 

그리고 마지막에 5를 더해서 반올림을 구현했다.

 

출력할때는 1000을 나눈 정수 부분과 1000로 모듈러 연산을 한 소수부분(fraction)을 따로 출력해주었다.

 

5가 정답일 때 5.00라고 출력해야 하므로 포맷 스트링에 0 extension도 해 주어야 한다.

 

%02d와 같이 하면 너비 2만큼 0을 꽉채워서 출력해준다.

 

구현 코드

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
int main() {
	int n, k;
	vector<ll> arr;
	cin >> n >> k;
	arr.resize(n);
	for (int i = 0; i < n; i++) {
		double tmp;
		cin >> tmp;
		arr[i] = (ll)(tmp * 1000);
	}
	sort(arr.begin(), arr.end());
	ll s = 0;
	for (int i = k; i + k < arr.size(); i++) {
		s += arr[i];
	}
	ll ans = s / (arr.size() - k - k) + 5;
	printf("%lld.%02lld\n", ans / 1000, ans % 1000 / 10);
	s = 0;

	s += k * arr[k];
	for (int i = k; i + k < arr.size(); i++) {
		s += arr[i];
	}
	s += k * arr[arr.size() - 1 - k];
	ans = s / arr.size() + 5;
	printf("%lld.%02lld\n", ans / 1000, ans % 1000 / 10);
}

 

+ Recent posts