※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1222번 문제인 홍준 프로그래밍이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/1222
1222번: 홍준 프로그래밍 대회
홍준이는 프로그래밍 대회를 개최했다. 이 대회는 사람들이 팀을 이루어서 참가해야 하며, 팀원의 수는 홍준이가 정해준다. 팀원이 홍준이가 정한 값보다 부족하다면, 그 팀은 대회에 참여할 수
www.acmicpc.net
처음에 문제를 "예선에 참가하는 사람을 최대화"하는 문제로 잘못 이해하고 풀었었다. 이후 문제를 제대로 이해한 뒤에도 잘못된 가정을 찾아내는 데에 시간이 많이 걸려 고생한 문제이다.
이 문제에서 구해야하는 것은 "본선에 참가하는 사람을 최대화(단, 팀은 둘 이상이 있어야 함)"하는 것이다.
이를 구하기 위해서는 1 이상 200만 이하의 각 수 K에 대하여 (K * (학생 수가 K의 배수인 학교의 수))의 최댓값을 구하면 된다.
각 학교의 학생수를 소인수분해하고, 그 결과를 이용해 모든 소인수를 구해내 학생수가 어떤 수의 배수가 될 수 있는지를 전부 기록하면 문제를 빠르게 해결할 수 있다.
각 수를 소인수분해할 때, 에라토스테네스의 체를 응용한 전처리(소수의 경우 0, 합성수의 경우 1 대신 해당 수를 나누는 가장 작은 소인수를 기록)로 일반적으로 잘 알려진 O(sqrt(N))의 약수 탐색 알고리즘보다 빠르게 모든 약수를 찾아낼 수 있다. (수 하나의 약수를 찾는 것은 O(sqrt(N))이 더 빠르나, 범위가 정해져있고 약수를 찾아야 하는 수가 많다면 위의 방법이 더 빠르다.)
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
int sieve[2000001];
ll cnt[2000001];
vector<pair<int, int>> p; // (소인수,cnt)
int psize;
void func(int idx, int val) {
if (idx == psize) cnt[val]++;
else {
int curval = 1, pp = p[idx].first, iterp = p[idx].second;
for (int i = 0; i <= iterp; i++) {
func(idx + 1, val * curval);
curval *= pp;
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
sieve[1] = 1;
for (int i = 2; i < 1414; i++) {
if (sieve[i]) continue;
for (int j = i * i; j < 2000001; j += i) {
if (sieve[j]) continue;
sieve[j] = i;
}
}
for (int i = 2; i < 2000001; i++) {
if (sieve[i] == 0) sieve[i] = i;
}
int Q; cin >> Q;
ll total = Q;
while (Q--) {
p.clear();
int N; cin >> N;
int prev = -1;
while (N > 1) {
int tmp = sieve[N];
if (tmp == prev)p.back().second++;
else prev = tmp, p.emplace_back(make_pair(tmp, 1));
N /= tmp;
}
psize = p.size();
func(0, 1);
}
for (ll i = 2; i < 2000001; i++) {
if (cnt[i] < 2) continue;
ll tmp = i * cnt[i];
if (tmp > total) total = tmp;
}
cout << total;
}
'BOJ' 카테고리의 다른 글
[BOJ 15510 // C++] League of Overwatch at Moloco (Easy) (0) | 2022.10.11 |
---|---|
[BOJ 15511 // C++] League of Overwatch at Moloco (Hard) (0) | 2022.10.10 |
[BOJ 14410 // C++] Pareto (0) | 2022.10.08 |
[BOJ 14413 // C++] Poklon (1) | 2022.10.07 |
[BOJ 25050 // C++] 최고의 간선 (0) | 2022.10.06 |