ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Algorithm-PS] 약수의 개수
    카테고리 없음 2024. 7. 3. 17:18

     

    알고리즘 문제를 풀 때

    종종 약수의 개수를 물어보는 문제들이 출제된다.

     

    입력 수를 number 라고 할 때,

    가장 쉬운 방법으로는 1부터 number로 number를 나눠서

    나누어 떨어지면 count를 1 증가시키면 된다.

    해당 방법의 시간 복잡도는 O(N)으로
    입력 수가 커짐에 따라 실행 시간이 비례적으로 증가한다는 것을 알 수 있다.

     

     

    그렇다면 효율적인 방법은 뭐가 있을까?

    나는 일단 단순하게 자기 자신(number)을 제외하면 모든 약수는 number를 2로 나눈 값보다

    작거나 같을 테니 1부터 (number / 2)로 number를 나눴었다.

    그러나 다른 사람들의 코드를 분석해본 결과 더 효율적인 방법이 있었다.

    √number 보다 작거나 같은 값으로 number를 나눠서

    나누어 떨어지면 count를 2번 증가시키면 된다.

    그러나 여기서 유의할 점이 있는데,

    number를 4라고 가정해보자.

    약수는 1, 2, 4로 총 3개의 약수의 개수가 있다.

    그러나 위의 알고리즘으로 진행한다면,

    √4인 2보다 작거나 같은 값, 1과 2로 4(number)를 나누면

    count가 4가 될 것이다.

    number를 1이라고 가정했을 때도

    약수는 1로 1이 반환이 되어야 하는데, 2가 반환될 것이다.

    즉 특정 약수의 제곱(^2) 값이 number와 같은 경우를 예외로 빼야하는 것이다. (count를 1번만 증가하는 걸로)

     

    이를 코드로 나타내자면

    ...
    
    //i * i <= n은 단순히 루트를 취해봐라 i <= √n 을 의미하는 것이다.
    for (int i = 1; i * i <= n; i++) { //i는 약수의 경우 수
    	
        // i^2이 n이라는 것은 i가 n의 약수라는 것을 내포하고 있음
        if (i * i == n) {
        	count++;
        }
        else if (n % i == 0) {
        	count += 2;
        }
      
        ...
    
    }
    
    ...

     

    이런 식으로 나타낼 수 있을 것 같다.

    특정 약수의 제곱이 number와 같은 경우엔 count를 1번만 해주고, 나머지의 경우엔 2번을 더해주면 된다.

     

     

    number의 약수의 절반이 √number 라는 증명은

    https://doodle-ns.tistory.com/32

     

    [노트] 모든 약수를 구하는 알고리즘은 O(sqrt(n))이다.

    학원 학생들이 약수를 모두 찾는 (또는 약수의 합, 개수를 구하거나, 소수 판별 등등) 코드를 어떻게 짜는지 살펴보면, 백이면 백 \(O(n)\) 알고리즘을 사용한다. 하지만 어떤 수의 모든 약수를 구

    doodle-ns.tistory.com

    이 글을 통해 자세히 볼 수 있다.

     

     

Designed by Tistory.