👀 문제 설명
홍준이는 프로그래밍 대회를 개최했다. 이 대회는 사람들이 팀을 이루어서 참가해야 하며, 팀원의 수는 홍준이가 정해준다. 팀원이 홍준이가 정한 값보다 부족하다면, 그 팀은 대회에 참여할 수 없다. 모든 팀은 같은 수의 팀원으로 이루어져 있다.
대회에 참여 의사를 밝힌 학교는 총 N개이다. 각 학교는 모든 학생이 참여할 수 있는 경우에만 대회에 참가한다. 즉, 남는 사람 없이 모든 학생이 팀에 들어갈 수 있어야 한다.
대회는 예선과 본선으로 구성되어 있다. 모든 팀은 같은 학교 소속으로 이루어져 있어야 한다. 예선에서 각 학교 1등팀만 본선에 진출한다.
홍준이의 대회는 올해가 첫 해이기 때문에, 많은 관심이 필요하다. 따라서, 본선에 참가하는 사람의 수를 최대가 되도록 팀원의 수를 정하려고 한다. 또, 본선이 지루해지는 것을 막기 위해 적어도 두 팀이 본선에 참가할 수 있어야 한다.
홍준이가 팀원을 몇 명으로 정해야 본선에 참가하는 사람의 수가 최대가 되는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 홍준이의 대회에 참여 의사를 밝힌 학교의 수 N (2 ≤ N ≤ 200,000)이 주어진다.
둘째 줄에는 각 학교 학생의 수가 주어진다. 학생의 수는 구간 [1, 2,000,000]에 포함된다.
출력
첫째 줄에 홍준이의 대회 본선에 참가하는 사람의 수의 최댓값을 출력한다.
예제 입력 1
3
1 2 4
예제 출력 1
4
예제 입력 2
2
1 5
예제 출력 2
2
예제 입력 3
5
4 6 3 8 9
예제 출력 3
9
✍🏻풀이
이 문제는 약수를 사용하는 문제이다.
예제3을 보면,
프로그래밍 대회에 참가하는 학교는 5개이고, 각 학교는 4, 6, 3, 8, 9명의 학생을 갖고 있다.
홍준이가 정한 팀원의 수 student라고 하자.
1) student = 4인 경우,
4명의 학생을 보유한 학교와
8명의 학생을 보유한 학교가 참가할 수 있다. 이 때 본선에 진출하는 학생수는 8명이 된다.
2) student = 6인 경우,
6명의 학생수를 보유한 학교만 참여할 수 있으므로 불가능하다.
3) student = 3인 경우,
6명의 학생을 보유한 학교와
3명을 보유한 학교,
9명을 보유한 학교가 참여할 수 있다. 이 때 본선에 진출하는 학생수는 9명이 된다.
4) student = 8인 경우,
8명을 보유한 학교만 참여할 수 있으므로 불가능하다.
5) student = 9인 경우,
9명을 보유한 학교만 참여할 수 있으므로 불가능하다.
본선에 진출하는 학생수의 최댓값은 9명이므로 답은 9가 된다.
문제를 보고 벡터를 써야겠다는 생각이 제일 처음 들었다.
먼저, 학교의 수 N과 각 학교의 학생수를 저장하는 vector<int> studentNumber를 선언했다.
그리고 for문으로 벡터에 접근, 각 인자의 result 값을 구했다.
for문을 두 번 사용하여 studentNumber[i]값을 약수로 갖는 값들이 몇 개인지 구했다. 이 값 * studentNumber[i]를 해서 답을 구했는데, timeout이 났다..! 검색해보니 이 문제는 벡터로 풀면 timeout이 발생하는듯 했다.
아래는 timeout이 발생한 코드이다.
//
// BOJ_1222.cpp
// Algorithm
//
// Created by 조수민 on 2020/07/23.
// Copyright © 2020 조수민. All rights reserved.
//
// 홍준 프로그래밍 대회(https://www.acmicpc.net/problem/1222)
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
int N; // 대회에 참가하는 학교의 수
vector<int> studentNumber; // 각 학교의 학생 수 벡터
// 이 문제는 벡터로 풀면 메모리가 터진다..!
void input()
{
cin >> N;
studentNumber.resize(N);
for (int i = 0; i < N; i++)
cin >> studentNumber[i];
}
int getMaxNum()
{
int max = 0; // 본선에 참가할 수 있는 사람의 수의 최댓값
// 벡터를 두 번 접근 -> 시간복잡도가 n의 제곱근 -> timeout이 난다.
for (int i = 0; i < studentNumber.size(); i++)
{
int schoolNum = 0;
int currentNum = studentNumber[i]; // 홍준이가 정한 팀원의 수
// 벡터를 다시 접근하여 currentNum으로 나누어 떨어지는 학교의 수가 몇인지 센다.
for (int j = 0; j < studentNumber.size(); j++)
{
if (studentNumber[j] % currentNum == 0)
schoolNum += 1;
}
// 학교의 수가 1이라면 continue로 건너뛴다. (적어도 두 팀이 본선에 참가해야 하기 때문)
if (schoolNum == 1)
continue;
int current = schoolNum * currentNum; // current는 currentNum이 studentNumber[i]일 때, 본선에 참가하는 사람의 수이다.
if (max < current) // max보다 current값이 크다면
max = current; // max를 current값으로 바꿔준다.
}
return max;
}
int main()
{
input();
cout << getMaxNum() << endl;
return 0;
}
벡터대신 배열을 사용해보았다.
schoolArray 배열을 사용했다. schoolArray[number]에 값을 저장하는 식으로 사용했다. 이 때, number는 학생수가 number인 학교가 몇 개인지 저장하는 역할을 한다.
즉, schoolArray[5] = 3이라면 학생수가 5명인 학교가 3개라는 뜻이다.
이후 for문을 사용하여 schoolArray[i] + schoolArray[2 * i] + schoolArray[3 * i] + ... 을 구한다.
즉, i를 약수로 갖는 값들이 몇 개인지 구하는 것이다.
이 수 * i를 이전에 구한 값과 비교해 더 큰 값을 저장해나가면 된다.
상수 선언
#define MAX 2000000
필요한 변수
int N : 대회에 참가하는 학교의 수
long long schoolArray[MAX + 1] : 학생수가 i인 학교가 몇개인지 저장하는 배열. ex) schoolArray[5] = 3일 경우, 학생수가 5명인 학교가 3곳이다.
알고리즘
위의 설명과 같다.
코드
//
// BOJ_1222.cpp
// Algorithm
//
// Created by 조수민 on 2020/07/23.
// Copyright © 2020 조수민. All rights reserved.
//
// 홍준 프로그래밍 대회(https://www.acmicpc.net/problem/1222)
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define MAX 2000000
int N; // 대회에 참가하는 학교의 수
long long schoolArray[MAX + 1];
void input()
{
cin >> N;
for (int i = 0; i < N; i++)
{
int number;
cin >> number;
schoolArray[number]++;
}
}
long getMaxNum()
{
long maxNum = 0;
for (int i = 1; i <= MAX; i++)
{
int count = 0; // 참가하는 학교의 수
/**
schoolArray[i] + schoolArray[2 * i] + schoolArray[3 * i] + ... 를 구할 수 있다.
즉, i를 약수로 갖는 값들이 몇 개인지 알 수 있다.
*/
for (int j = i; j <= MAX; j += i)
count += schoolArray[j];
if (count < 2) // 본선에는 적어도 2팀이 참가해야 한다.
continue;
maxNum = max(maxNum, (long)count * (long) i); // 학생수 = 각 팀을 구성하는 학생 수 * 대회 참여가 가능한 학교 수
}
return maxNum;
}
int main()
{
input();
cout << getMaxNum() << endl;
return 0;
}
'숨막히는 알고말고 > 문제 풀이' 카테고리의 다른 글
[Programmers] 가장 큰 수 (0) | 2020.10.25 |
---|---|
[Baekjoon] 순열 사이클(BOJ 10451) (0) | 2020.10.23 |
[Baekjoon] 추월(BOJ 2002) (0) | 2020.07.23 |
[Baekjoon] 기상개스터(BOJ 10709) (0) | 2020.07.15 |
[Baekjoon] 피보나치 수의 확장(BOJ 1788) (0) | 2020.07.15 |