PS
solved.ac [Class 2] 정리중...
왕방토
2023. 2. 2. 15:57
728x90
의외로 까다로운 문제가 있다
다 보지는 않았지만 꼭 풀어봤으면 하는 문제는 별표 ( 너무 기본적인 문제는 어디선가 풀었을거라고 생각해서 제외 )
- 브루트포스
- 기하, 비교 조건문(if)
★단어 정렬 : string과 scanf/printf 를 같이 쓰는 연습을 하는데 좋고, 조건이 여러개인 정렬이 중요함
- 조건이 두 개 이상인 정렬
- 중복 제거
- (char* -> string / string -> char*)
- https://ddingji.tistory.com/106
[C++] 1181: 단어 정렬
solved.ac에서 class3 필수문제들 다시 풀어보자! 하다가 발견한 문제인데 C++을 쓰면서 scanf/printf를 사용하는 나같은 사람에게는 조금 까다로울 수 있는 문제라서 다시 풀어봤다 이 문제를 푸는 방법
ddingji.tistory.com
- 문자열 처리
★영화감독 숌 : 규칙을 찾는문제일 거 같은데 브루트포스인 점이 특이함
- 브루트포스
★★★랜선 자르기
- parametric search(이분탐색 응용)
- (+ 자료형 잘 살피기)
- 스택 사용
★수 찾기
- 수들 사이에서 수 찾기 -> "수들" 을 정렬하여 binary search
- 에라토스테네스의 체 (안써도 풀리려나?)
- 근데 에라토스테네스의 체가 원래 모든 숫자들을 prime이라고 가정하고 푸는데
- 늘 반대로 푸는 것이 마음에 안들어서 저대로 풀었더니
- 넘 헷갈린다 ㅋㅋ not_prime 이 아닌거면.. prime이지? 하고 헷갈림
#include <iostream>
#include <algorithm>
using namespace std;
bool not_prime[1000001];
int main() {
int M, N;
scanf("%d%d", &M, &N);
not_prime[1] = true;
for (int i = 2; i <= N; i++) {
if (not_prime[i]) continue;
for (int j = 2*i; j <= N; j += i) {
not_prime[j] = true;
}
}
for (int i = M; i <= N; i++) {
if (!not_prime[i]) printf("%d\n", i);
}
}
- 대충 이렇게 생겼는데.. 또 지금보니까 안헷갈리는거 같기도 한데 is_prime 이런거 쓰다가 이렇게 쓰면 헷갈린다 ㅋㅋ
- 구현
- priority queue 이용하면 좀 더 쉽게 구할 수 있다
- -> 최대가 아닌 값을 큐에서 빼서 다시 넣는 것은 priority queue에(최대값을 구하는데) 아무 영향을 미치지 않으므로 최대인 값을 빼 줄 때만 pq의 top을 pop해주면 된다
- 그리고.. 인덱스가 M인 파일을 굳이 추적해도 되고..?(그렇게 큰 오버헤드는 아니긴 함) 아니면 애초에 큐에 파일을 넣을 때 처음 인덱스를 같이 넣어줘도 된다(메모리 더 사용!)
- 에라토스테네스의 체(안써도 풀릴듯)
★통계학
- 허어......
- <cmath>의 round 함수........
- float round(float) / doule round(double) ... 이런 식으로 float에 대해서도, double에 대해서도 다 처리해주는게 있는데
- 입력이 float든 double이든 결과는 (float) X.000... / (double) X.000... 이라는 건데
- 얘를 int로 casting(자름 변환) 한다고 해봐야 X가 되는건데
- float로 할 때는 float가 되지만 double일 때는 double이 안되는 게 참 신기하다
- 결국 그러면 부동소수점 문제라는거인데.. round 함수 문제인건 아닌게 되니까
- 결론: float말고 double 씁시다 아니 long double 씁시다 굳
- 추가로 최빈값 어렵다는 말이 많은데 cmp 함수 만드는게 어렵다는건 아닐테고
- 입력을 받고 cnt를 세어주면서 해당 입력값과 cnt를 같이 저장하는 자료구조를 생각해 낸 다음에
- 잘 정렬(게다가 기준이 두개!) 하는 것 까지가 어렵다는 것 같다 음 그렇게 생각하면 좀 어려운거 같기도...
틀린코드
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
struct info {
int num, cnt;
};
int arr[500000];
int cnt[8001];
bool cmp(const info& i1, const info& i2) {
if (i1.cnt == i2.cnt) return i1.num < i2.num;
return i1.cnt > i2.cnt;
}
int main() {
int N;
scanf("%d", &N);
float sum = 0;
for (int i = 0; i < N; i++) {
scanf("%d", &arr[i]);
cnt[arr[i] + 4000]++;
sum += arr[i];
}
int ans1 = round(sum / N);
sort(arr, arr + N);
int ans2 = arr[N / 2];
int ans3;
vector<info> v;
for (int i = 0; i < 8001; i++) {
if (cnt[i] == 0) continue;
v.push_back({ i - 4000, cnt[i] });
}
sort(v.begin(), v.end(), cmp);
if (v.size() >=2 && v[0].cnt == v[1].cnt) ans3 = v[1].num;
else ans3 = v[0].num;
int ans4 = arr[N - 1] - arr[0];
printf("%d\n%d\n%d\n%d", ans1, ans2, ans3, ans4);
}
(코드보면 N이 int긴 하지만 int & float 연산이라 round의 입력 float로 들어감)
AC 코드 (float sum = 0 -> double sum = 0 의 차이 뿐)
(여기서는 round 입력 double)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
struct info {
int num, cnt;
};
int arr[500000];
int cnt[8001];
bool cmp(const info& i1, const info& i2) {
if (i1.cnt == i2.cnt) return i1.num < i2.num;
return i1.cnt > i2.cnt;
}
int main() {
int N;
scanf("%d", &N);
double sum = 0;
for (int i = 0; i < N; i++) {
scanf("%d", &arr[i]);
cnt[arr[i] + 4000]++;
sum += arr[i];
}
int ans1 = round(sum / N);
sort(arr, arr + N);
int ans2 = arr[N / 2];
int ans3;
vector<info> v;
for (int i = 0; i < 8001; i++) {
if (cnt[i] == 0) continue;
v.push_back({ i - 4000, cnt[i] });
}
sort(v.begin(), v.end(), cmp);
if (v.size() >=2 && v[0].cnt == v[1].cnt) ans3 = v[1].num;
else ans3 = v[0].num;
int ans4 = arr[N - 1] - arr[0];
printf("%d\n%d\n%d\n%d", ans1, ans2, ans3, ans4);
}
- 큐
- 브루트포스
★★★나무 자르기
랜선 자르기와 거의 똑같은 문제였던거 같은데 필수
- 스택 구현
- 큐 구현
- 덱 구현