[C++] 백준(BOJ) - 3474 : 교수가 된 현우

인프런에 있는 큰돌님의 강의 10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트를 듣고 정리한 필기입니다.

문제

백준(BOJ) - 3474 : 교수가 된 현우(링크)

알고리즘의 킹갓제너럴엠퍼러마제스티충무공알고리즘마스터 현우가 교수로 취임하였다!

그러나 학생들에게 크나큰 기대를 품고 첫 수업에 들어갔던 현우는 아무도 외판원 순회 문제(Traveling Salesman Problem, TSP)를 풀지 못하는 것을 보고 낙심하였다.

그 와중에 학생 남규는 TSP를 완전탐색으로 풀려고 하였고, 현우는 그걸 보고 경악을 금치 못한다. 왜냐면 TSP를 완전탐색으로 풀려면 O(N!)의 시간이 소모되는데, 이는 경악을 금치 못할 시간이기 때문이다.

그러나 남규는 O(N!)이 왜 큰지도 잘 모른다. 그래서 현우는 더더욱 경악을 금치 못하고, N!이 얼마나 큰지 대략적으로나마 알려주기 위해, 자연수 N이 주어지면 N!의 오른쪽 끝에 있는 0의 개수를 알려주기로 하였다.

그러나 현우는 경악을 금치 못하여 지금 코딩을 할 수 없는 상황이다. 여러분이 현우를 대신하여 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어지고, 이어서 T개의 줄에 정수 N이 주어진다(1 <= N <= 1000000000).

출력

각 줄마다 N!의 오른쪽 끝에 있는 0의 개수를 출력한다.

알고리즘

  1. 구현
  2. 수학
  3. 정수론

풀이

  • 시간복잡도를 고려하여 문제를 풀이할 최적의 방법을 생각해 낸다
  • 소인수분해의 개념 (25는 5의 제곱이다 => 5가 2개 나옴)
    • 소인수분해 dp 배열처럼 만들어버리기 (cnt만 필요하므로 int형 res2, res5만으로 카운팅)

코드

// BOJ - 3474 : 교수가 된 현우
#include<bits/stdc++.h>
using namespace std;
const int INF = 2147000000;

int t;
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        int res2 = 0, res5 = 0;

        // 10
        // 1 2 3 4 5 6 7 8 9 10
        //   1   1   1   1   1  => 5 (10/2)
        //       1       1      => 2 (10/4)
        //               1      => 1 (10/8) => 8
        for (int i = 2; i <= n; i *= 2)
        {
            res2 += n / i;
        }
        for (int i = 5; i <= n; i *= 5)
        {
            res5 += n / i;
        }
        cout << min(res2, res5) << '\n';
    }
    return 0;
}

평가

  • 간단한 문제이나 제곱 수에 대한 내용을 자칫 잘못하면 놓칠 수 있음을 유의

© 2023 Jinsoo Lee. All rights reserved.

Powered by Hydejack v9.1.6