Coding Interview

3-5. [구간합] 나머지 합 구하기

milliwonkim 2023. 1. 23. 16:53
반응형
SMALL

나머지 합

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 256 MB 20710 6147 4487 28.017%

문제

수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오.

즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j) 쌍의 개수를 구해야 한다.

입력

첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 106, 2 ≤ M ≤ 103)

둘째 줄에 N개의 수 A1, A2, ..., AN이 주어진다. (0 ≤ Ai ≤ 109)

출력

첫째 줄에 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 출력한다.

예제 입력 1 복사

5 3
1 2 3 1 2

예제 출력 1 복사

7

출처

  • 문제를 만든 사람: baekjoon
  • 데이터를 추가한 사람: cs71107

풀이

 

다음의 두 조건을 만족할 때 answer의 숫자를 늘린다.

 

1. 구간합 % 3 === 0인 경우 answer의 갯수에 추가 => 3

2. 구간합 % 3을 했을 때의 나머지 값으로 만든 새로운 array에서 같은 array[i] === array[j]가 있을 경우, 2개를 선택했을 때의 조합(C)갯수를 answer 갯수에 추가 => 3 + 1 = 0을 2개를 뽑을 경우 + 1을 2개 뽑을 경우 = 4

 

따라서 3 + 4 = 7

 

코드

const A = [1, 2, 3, 1, 2];
const S = [0, 0, 0, 0, 0];
const m = 3;
let answer = 0;
const C = [0, 0, 0];

for (let i = 0; i < A.length; i++) {
  S[i] = S[i - 1 >= 0 ? i - 1 : 0] + A[i];
}

for (let i = 0; i < S.length; i++) {
  const left = S[i] % m;
  if (left === 0) answer += 1;
  C[left] += 1;
  S[i] = left;
}

for (let i = 0; i < m; i++) {
  if (C[i] > 1) {
    console.log((C[i] * (C[i] - 1)) / 2);
    
    // 조합공식 참고 
    answer += parseInt((C[i] * (C[i] - 1)) / 2); 
  }
}

console.log(answer);

 

참고: 조합공식

반응형
LIST