파이썬 코딩테스트 강좌, 오일러 피 함수 구현하기

안녕하세요! 오늘은 파이썬으로 오일러 피 함수(Euler’s Totient Function)를 구현하는 방법을 알아보겠습니다. 이 글에서는 오일러 피 함수의 정의와 성질을 살펴보고, 효율적으로 구현하는 방법에 대해 단계적으로 설명할 것입니다.

1. 오일러 피 함수란?

오일러 피 함수 φ(n)은 1과 n 사이의 정수 중에서 n과 서로소인 수의 개수를 나타내는 함수입니다. 즉, φ(n)은 n과 공약수를 가지지 않는 수의 수를 의미합니다. 예를 들어:

  • φ(1) = 1 (1은 자신만과 서로소)
  • φ(2) = 1 (1만이 2와 서로소)
  • φ(3) = 2 (1, 2가 3과 서로소)
  • φ(4) = 2 (1, 3이 4와 서로소)
  • φ(5) = 4 (1, 2, 3, 4가 5와 서로소)

2. 오일러 피 함수의 성질

오일러 피 함수는 몇 가지 중요한 성질을 가지고 있습니다:

  • 만약 n이 소수 p라면, φ(p) = p – 1
  • 만약 n이 소수의 거듭제곱 p^k라면, φ(p^k) = p^k(1 – (1/p))
  • n이 두 정수 a와 b의 곱이라면, φ(ab) = φ(a) * φ(b) * (1 – (1/gcd(a,b)))

2.1 예시

주어진 수 n의 오일러 피 함수 값 φ(n)을 구해야 한다면, n의 소인수를 찾아야 합니다. 예를 들어 n = 12이 주어진 경우, 소인수는 2와 3이며, 이 두 소수에 대한 φ 값을 사용하여 φ(12)를 계산할 수 있습니다.

3. 오일러 피 함수 구현 방법

지금부터 φ(n)을 효율적으로 구현하는 방법을 알아보겠습니다. 기본적인 접근 방식은 각각의 수를 확인해서 서로소인 수의 개수를 세는 것인데, 이는 비효율적이므로 개선할 필요가 있습니다.

3.1 에라토스테네스의 체 방식

오일러 피 함수를 효율적으로 구현하는 방법 중 하나는 에라토스테네스의 체(Sieve of Eratosthenes)의 개념을 사용하는 것입니다. 다음은 φ(n)을 계산하는 로직입니다:

def euler_totient(n):
    # 1부터 n까지의 페어 배열 초기화
    phi = list(range(n + 1))
    
    # 에라토스테네스의 체를 사용하여 오일러 피 함수 값 계산
    for i in range(2, n + 1):
        if phi[i] == i:  # i가 소수일 경우
            for j in range(i, n + 1, i):
                phi[j] *= (i - 1)
                phi[j] //= i
    return phi

3.2 코드 분석

위의 코드는 다음과 같이 작동합니다:

  1. φ 배열을 1부터 n까지 초기화합니다. 즉, φ[i]는 처음에는 i로 설정됩니다.
  2. 2부터 n까지의 모든 수 i에 대해, i가 소수인지 확인합니다. 이 경우, φ 배열을 업데이트합니다.
  3. j는 i의 배수로 설정하여 해당 배수의 φ 값을 갱신합니다.

4. 시간 복잡도 분석

이 알고리즘의 시간 복잡도는 O(n log log n)입니다. 이는 에라토스테네스의 체와 유사하여, 매우 효율적으로 φ(n)을 계산할 수 있습니다. 작은 n의 경우에만 이 알고리즘을 사용하실 수 있으나, 큰 n의 경우에도 충분히 빠른 성능을 유지합니다.

5. 예제

다음은 이 알고리즘을 사용하여 n = 10까지의 오일러 피 값을 계산하고 출력하는 예제입니다:

if __name__ == "__main__":
    n = 10
    result = euler_totient(n)
    print(f"n = {n} 까지의 오일러 피 함수 값: {result[1:]}")

5.1 출력 예시

n = 10 까지의 오일러 피 함수 값: [1, 1, 2, 2, 4, 4, 6, 6, 8, 4]

6. 결론

이번 글에서는 오일러 피 함수의 정의, 성질, 구현 방법에 대해 알아보았습니다. 고전적인 방식 대신 에라토스테네스의 체를 활용하면 효율적으로 φ(n)을 구할 수 있다는 점이 인상적입니다. 앞으로 다른 알고리즘과 자료구조를 배우면서 더 복잡한 문제들도 해결해 나가길 바랍니다.

7. 참고 자료

지금까지 함께 해주셔서 감사합니다! 다음 시간에도 더 유익한 알고리즘 강좌로 찾아뵙겠습니다.