백준 17427

Jb·2023년 10월 25일

백준

목록 보기
1/3

약수의 합

입력받은 수의 약수의 약수의합을 구하는 문제이다
약수의 약수의 합이라는 말처럼 이중반복문을 쓰면 될꺼같은 느낌이 들었다.
하지만 scanner와 반복문2번과 if문 두번을 쓰니 타임아웃이 떠버렸다


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        long result = 0; // g(N) 값을 저장할 변수

        for (int i = 1; i <= N; i++) {
            result += f(i);
        }

        System.out.println(result); // 최종 g(N) 값을 출력
    }

    // f(A)를 계산하는 함수
    public static long f(int A) {
        long sum = 0;
        int sqrtA = (int) Math.sqrt(A);
        for (int i = 1; i <= sqrtA; i++) {
            if (A % i == 0) {
                sum += i; // i를 sum에 더함
                if (i != A / i) { // i와 A/i 가 다를 경우에만 추가
                    sum += A / i;
                }
            }
        }
        return sum;
    }
}

해결방법으로는
다른 알고리즘:Dynamic Programming

DP(Dynamic Programming)는 복잡한 문제를 간단한 여러 하위 문제로 나누어 해결하는 방법론이다. 각 하위 문제의 해결을 저장하고, 그 해결을 이용해서 원래 문제를 해결하는 것이 핵심이다.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();

        long[] dp = new long[N + 1];  // dp[i]는 i의 약수의 합을 저장합니다.

        for (int i = 1; i <= N; i++) {
            for (int j = 1; j * i <= N; j++) {
                dp[i * j] += i;
            }
        }

        long result = 0;
        for (int i = 1; i <= N; i++) {
            result += dp[i];
        }

        System.out.println(result);
    }
}

느낀점은 타임아웃을 처음 경험해봤다.
간단한 문제만 풀어서 알고리즘을 적용을 안하고 문제를 보고 for문 이나 if문 여러번 쓰면 되겠지라고 생각했었다
하지만 최적화를 하면서 한줄의 코드를 재활용해서 시간을 줄이는게 더 효과적인 방법이구나를 꺠달았다

0개의 댓글