ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 10986번 - 나머지 합
    알고리즘/백준 2023. 7. 30. 13:33

    1️⃣ 부분 합, 모듈러 연산

     

    ✏️ 풀이 과정

    N이 1000000까지 가능하기 때문에 O(N^2)의 알고리즘으로는 해결할 수 없습니다. 모든 결과를 구하는 것이 아니라 개수만을 구하면 되기 때문에 O(N)의 알고리즘으로 이를 해낼 수 있는지 알아봐야 합니다.

     

    여기서 문제를 해결한 방법은 부분합을 사용한 것입니다. 부분합을 사용했을 때의 효과는 부분합 배열의 특정 인덱스에서 또 다른 인덱스의 값을 빼는 계산을 통해 특정 구간의 합을 알 수 있다는 것입니다.

     

    여기서 M으로 나누어 떨어지는 구간을 골라야 하기 때문에 모든 계산에 M에 대한 모듈러 연산을 적용하면 더 간단하게 문제를 해결할 수 있습니다. 사칙연산에 대해 결합법칙이 성립하기 때문에 항상 적용해도 무방합니다.

     

    문제 해결 아이디어는 부분합 계산 배열에서 모듈러 연산의 결과가 같은 인덱스끼리 묶어 하나의 구간을 찾아낼 수 있다는 것입니다. 주의할 점은 3개, 4개 등 2개를 초과하는 경우를 고려하지 않아야 한다는 것입니다. 그 이유는 예를 들어 1 1 1이 있다고 할 때 인덱스 0과 2를 잡으면 0, 1, 2 모두를 선택한 것과 같은 구간이 되기 때문에 중복계산이 됩니다.

     

    부분합에 모듈러 연산을 적용한 결과가 0 0 1 0 1 이라고 할 때 가능한 구간의 조합은 0 세 개 중 두 개를 고른 것과 1 두 개 중 두 개를 고른 것의 합에 0 하나씩만 고른 것을 합한 3C2 + 2C2 + 3C1 = 7이 됩니다. 0 이외의 경우에는 한 개만을 선택했을 때 0이 되지 않기 때문에 한 개를 고른 경우를 고려하지 않습니다. 두 부분합 결과를 빼야 0이 나오기 때문입니다. (가열 초기 배열이 1 2 1이고 M이 3이라고 하면 부분합은 1 3 4 == 1 0 1이 됩니다. 인덱스 2까지의 부분합에서 인덱스 0까지의 부분합을 빼면 결과가 3이 되는데 이러한 원리로 0 이외의 경우에 부분합 0인 구간을 얻을 수 있습니다.)

     

    즉 0의 경우 개수C1과 개수C2를 계산하고 나머지 숫자의 경우 개수C2를 하여 모두 더하면 결과가 나오게 됩니다.

     

    ⏱ 시간 복잡도

    부분합 계산은 O(N)이며 컴비네이션 계산 또한 식을 이용하면 O(N)시간 내에 끝낼 수 있습니다. 따라서 전체 시간 복잡도는 O(N)이 되어 제한 시간 내에 해결할 수 있습니다.

     

    💻 코드

    JavaScript

    const input = require("fs")
        .readFileSync(process.platform === "linux" ? "/dev/stdin" : "input.txt")
        .toString()
        .trim()
        .split("\n");
    
    const [N, M] = input[0].split(" ").map(Number);
    const remainder = input[1].split(" ").map((item) => Number(item) % M);
    const partialSum = [remainder[0]];
    const cnt = Array(N).fill(0);
    cnt[partialSum[0]]++;
    for (let i = 1; i < N; i++) {
        partialSum[i] = (partialSum[i - 1] + remainder[i]) % M;
        cnt[partialSum[i]]++;
    }
    let res = cnt[0];
    for (let i = 0; i < N; i++) {
        res += (cnt[i] * (cnt[i] - 1)) / 2;
    }
    
    console.log(res);

    '알고리즘 > 백준' 카테고리의 다른 글

    2580번 - 스도쿠  (0) 2023.08.01
    16637번 - 괄호 추가하기  (0) 2023.08.01
    5639번 - 이진 검색 트리  (0) 2023.07.26
    15663번 - N과 M (9)  (0) 2023.07.26
    1976번 - 여행 가자  (0) 2023.07.25
Designed by Tistory.