※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 23615번 문제인 Product이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/23615
입력으로 주어지는 수가 0 또는 음의 정수일 수 있다는 점에 유의하자.
주어지는 수에 0이 포함되어 있는 경우, 0이 하나라면 불가능하고 둘 이상이면 항상 가능함을 어렵지 않게 관찰할 수 있다. 아래에서는 주어지는 수에 0이 포함되어있지 않은 경우만을 생각한다.
어떤 한 수와 다른 모든 수의 곱이 같다는 것은 그 하나의 수가 모든 수의 곱의 제곱근과 같아야 함을 관찰할 수 있다. 이 때 제곱근은 양의 제곱근과 음의 제곱근 둘 중 어떤 것이어도 상관없다. 이를 이용하면 풀이를 어렵지 않게 구성할 수 있다.
그러나 모든 수의 곱으로 가능한 값은 매우 크므로 직접 모든 수를 곱하는 것은 매우 느릴 것이다. 이 부분은 어떻게 최적화할 수 있을까? 간단한 방법 중 하나는 주어지는 수의 절댓값이 10억 이하임을 이용하는 것이다. 구체적으로, 이 중 하나의 값이 제곱근이어야 하므로 모든 수의 곱의 절댓값이 10억의 제곱보다 커진다면 주어진 수에서 제곱근을 더 이상 고를 수 없음을 알 수 있다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
typedef __int128 lll;
lll prd = 1; ll L, R;
int zcnt; bool WA;
int N;
vector<int> vec;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N; vec.reserve(N);
while (N--) {
int x; cin >> x;
if (x == 0) {
zcnt++;
continue;
}
prd *= x;
if (prd > 1000000000000000000LL || prd < -1000000000000000000LL) WA = 1;
if (WA) continue;
vec.emplace_back(x);
}
if (zcnt) {
if (zcnt == 1) cout << "No";
else {
cout << "Yes" << '\n';
cout << 0;
}
return 0;
}
if (WA || prd < 0) {
cout << "No";
return 0;
}
L = 1, R = 1000000000;
while (L < R) {
ll mid = (L + R) / 2;
if (mid * mid < prd) L = mid + 1;
else R = mid;
}
if (L * L != prd) {
cout << "No";
return 0;
}
for (auto &x:vec) {
if (abs(x) == L) {
cout << "Yes\n";
cout << x;
return 0;
}
}
cout << "No";
}
728x90
'BOJ' 카테고리의 다른 글
[BOJ 1229 // C++] 육각수 (1) | 2024.10.18 |
---|---|
[BOJ 1341 // C++] 사이좋은 형제 (2) | 2024.10.17 |
[BOJ 10009 // C++] Loteria 2 (4) | 2024.10.15 |
[BOJ 18066 // C++] Move & Meet (7) | 2024.10.14 |
[BOJ 13021 // C++] 공 색칠하기 (1) | 2024.10.11 |