백준 문제
백준 16563번 (어려운 소인수분해) c++
kangyuseok
2021. 8. 31. 18:21
728x90
16563번: 어려운 소인수분해
첫째 줄에는 자연수의 개수 N (1 ≤ N ≤ 1,000,000)이 주어진다. 둘째 줄에는 자연수 ki (2 ≤ ki ≤ 5,000,000, 1 ≤ i ≤ N)가 N개 주어진다.
www.acmicpc.net
단순히 백준 11653(소인수분해)문제와 비슷한줄 알고 바로 똑같이 코드를 작성해 주었습니다.
#include<iostream>
using namespace std;
int main() {
ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
int n;
cin >> n;
while (n--) {
int k;
cin >> k;
for (int i = 2; i * i <= k; i++) {
if (k % i)
continue;
while (k % i == 0) {
cout << i<<' ';
k /= i;
}
}
if (k != 1)
cout << k << '\n';
else cout << '\n';
}
return 0;
}
하지만 70% 쯤에서 시간초과가 발생하였고 문제를 자세히 읽어보니 자연수의 개수(N)이 1000000개
자연수 K 의 범위는 무려 2<=K<=50000000 이었습니다. 따라서 소인수분해를 하는 과정에서 시간초과가 날것이라고 생각했습니다.
그래서 생각한 방법이 에라토스테네스의 체를 이용해 5000000이하의 범위의 소수를 미리 구해 배열에 저장하여
그 배열에 있는 숫자로만 소인수분해를 하는 방법을 시도해봤습니다.
먼저 에라토스테네스의 체를 만들기 위해 배열의 인덱스 번호에 맞는 value값을 할당해 주었습니다.
int arr[5000001];
for (int i = 0; i < 5000001; i++) {
arr[i] = i;
}
그 다음 벡터 v를 선언해 소수만 들어갈 공간을 만들어 주고 에라토스테네스의 체 방법으로 소수만 걸러내어
벡터 v 에 저장해주었습니다.
vector<int>v; //소수만 저장할 공간
for (int i = 2; i < 5000001; i++) {
if (arr[i] == 0)
continue;
v.push_back(i); //소수 저장
for (int j = i+i; j < 5000001; j += i) {
if (arr[j] == 0)
continue;
arr[j] = 0;
}
}
그 이후는 맨 처음 소인수분해 방식과 유사 합니다. v[i]는 무조건 소수이므로 소수로만 연산을 할 수 있게 되었습니다.
while (n--) {
int k;
cin >> k;
for (int i =0; v[i]*v[i] <= k; i++) {
if (k % v[i])
continue;
while (k % v[i] == 0) {
cout << v[i]<<' ';
k /= v[i];
}
}
if (k != 1)
cout << k << '\n';
else cout << '\n';
}
전체 코드입니다.
#include<iostream>
#include<vector>
using namespace std;
vector<int>v;
int arr[5000001];
int main() {
ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
int n;
cin >> n;
for (int i = 0; i < 5000001; i++) {
arr[i] = i;
}
for (int i = 2; i < 5000001; i++) {
if (arr[i] == 0)
continue;
v.push_back(i);
for (int j = i+i; j < 5000001; j += i) {
if (arr[j] == 0)
continue;
arr[j] = 0;
}
}
while (n--) {
int k;
cin >> k;
for (int i =0; v[i]*v[i] <= k; i++) {
if (k % v[i])
continue;
while (k % v[i] == 0) {
cout << v[i]<<' ';
k /= v[i];
}
}
if (k != 1)
cout << k << '\n';
else cout << '\n';
}
return 0;
}