넘치게 채우기

[BOJ] 9326 - MI6 본문

PS/BOJ

[BOJ] 9326 - MI6

riveroverflow 2025. 6. 8. 00:34
반응형

https://www.acmicpc.net/problem/9326

BOJ - MI6

문제 유형: 수학, 정수론, 소수판정

문제 난이도: Gold III

시간 제한: 1초

메모리 제한: 128MB

 

문제

MI6는 스파이의 신원을 확인하기 위해서 스파이 식별 코드(Spy Identification Code, SIC)를 사용한다. 예를 들어, 제임스 본드의 SIC는 7이다.

MI6는 스파이의 그룹과 그룹에 속하는 스파이를 쉽게 알아볼 수 있게 하기 위해 SIC를 할당한다. 그룹은 상태 코드로 나타낼 수 있는데, 상태 코드는 그룹에 속하는 모든 스파이의 SIC를 곱한 값이다.

상태코드의 효율성을 위해, 2보다 크거나 같은 모든 상태코드에 대해서, 각 상태코드를 가지는 스파이 그룹이 유일하게 존재하고, 각 스파이 그룹사이의 상태코드 값이 다르게 되도록 SIC를 배정하려 한다.

상태 코드가 주어졌을 때, 그 그룹에 속하는 스파이의 SIC를 모두 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 테스트 케이스의 수가 주어진다. 테스트 케이스의 개수는 100개를 넘지 않는다. 각 테스트 케이스의 첫째 줄에는 상태 코드 c (2 ≤ c ≤ 10^9)가 주어진다.

 

출력

각 테스트 케이스 마다, 입력으로 주어진 상태 코드에 속하는 스파이의 SIC를 오름차순으로 출력한다. SIC 사이에는 공백을 하나 출력한다.

 

풀이

유일하게 스파이 그룹을 구성하려면, 다음과 같이 구성하여야 한다:

인수분해 시, 소수의 2의 승수번째 제곱들의 곱으로만 이루어져야 한다.

즉, 소인수들의 1, 2, 4, 8, ...승들의 곱으로만 이루어져야 한다.

예제가 큰 힌트가 되어준다.

 

소인수 2부터 시작해서, 소인수의 제곱이 c보다 작은동안, 다음을 반복한다:

 1. c % i로 나누어떨어지는 동안, c에 i를 나누면서 i가 몇 번 곱해지는지 카운트해준다.

 2. 약수로 i ^ cnt를 가지는 것을 알았으니, cnt를 이진 표현 했을 때, 1인 자릿수들에 대해 스파이의 구성 요소로 넣어준다.
예를 들면, 2를 6개 가진다면, 2^2 * 2^4를 가진다는 뜻이다.

만약 루프가 끝나고 c가 1보다 크다면, sqrt(c)보다 큰 약수가 하나 남았다는 뜻인데, 남는 경우, 이는 큰 수의 스파이 구성원이 됨을 알 수 있다. 작은 소인수들로 최대한 나눈 나머지이기 때문이다.

 

이렇게 구성원들을 모은 배열을 오름차순 정렬하고, 출력해주면 된다.

 

코드

C++

#include <bits/stdc++.h>

using namespace std;
using ll = long long;

ll bpow(ll base, ll exp) {
    ll res = 1;
    while (exp) {
        if (exp & 1) {
            res = res * base;
        }
        exp >>= 1;
        base = base * base;
    }

    return res;
}

void solve() {
    ll c;
    cin >> c;

    vector<int> ans;

    ll i = 2;
    while (c > 0 && i * i <= c) {
        ll cnt = 0;
        while (c % i == 0) {
            cnt++;
            c /= i;
        }
        if (cnt == 0) {
            i++;
            continue;
        }
        int shift = 0;
        while (cnt) {
            if (cnt & 1) {
                ans.emplace_back(bpow(i, 1 << shift));
            }
            cnt >>= 1;
            shift++;
        }
        i++;
    }
    if (c > 1) {
        ans.emplace_back(c);
    }
    sort(ans.begin(), ans.end());

    for (const auto &elem : ans) {
        cout << elem << " ";
    }
    cout << "\n";
}

int main(int argc, char *argv[]) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 15662 - 톱니바퀴(2)  (0) 2025.06.09
[BOJ] 크게 만들기  (0) 2025.06.08
[BOJ] 14616 - Explore Space  (0) 2025.06.08
[BOJ] 10881 - 프로도의 선물 포장  (0) 2025.06.06
[BOJ] 1823 - 수확  (0) 2025.06.04