알고리즘/코딩 테스트
[백준 10986] 나머지 합 - javascript,node.js,구간합,누적합
Judith Hopps
2023. 2. 13. 14:59
반응형
문제링크 : https://www.acmicpc.net/problem/10986
10986번: 나머지 합
수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오. 즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j)
www.acmicpc.net
알고리즘 :
1. n개의 수를 누적합을 저장한다.
2. 아래 구간합의 나머지 수학 공식을 알아야 한다.
- 즉 총합의 나머지가 0과 같아야 한다 했으니 결국 좌변의 합에 % m을 한 것과 우번의 합에 % m을 한것이 같아야 한다.
3. 조합을 이용한다. 즉 다른 n개 중 순서 상관없이 r개를 뽑는다.
n!/(n-r)!r!
즉 하나의 식으로 생각하면
psum : [ 1, 3, 6, 7, 9 ]
psum % m : [ 1, 0, 0, 1, 0 ]
0이 3개, 1이 2개이다.
즉 정답이 되는 경우의 수는
0인 psum 3개 + (0의 개수=3)*(3-1)/2 + (1의 개수=2)*(2-1)/2 이다.
문제풀이 :
1. 누적합을 구해준다.
const [n,m] = input[0].split(' ').map(Number)
const arr = input[1].split(' ').map(Number)
let answer = 0;
const psum = new Array(n+1).fill(0)
arr.forEach((v,i)=>{
psum[i+1] = psum[i] + v
})
for(let i=1;i<psum.length;i++){
let sum = psum[i];
if(sum%m===0) answer++;
if((sum-psum[i-1])%m===0){
answer++
}
}
2. 누적합을 m으로 나눈 수로 index 0을 제외한 값을 map으로 저장한다.
이때 키는 나머지 값, value는 개수이다.
const map = new Map();
psum.slice(1).forEach(v=>{
map.set(v%m,(map.get(v%m)||0)+1)
})
3. map을 for문 돌려서 각각의 식을 구해 더해준다.
const check = [...map]
check.forEach(v=>{
answer+=(v[1]*(v[1]-1))/2
})
4. 0의 개수를 더해주고 출력한다.
answer+=map.get(0)||0
5. 최종 코드
const filePath = require('path').join(__dirname, '/test.txt');
const input = require('fs').readFileSync(filePath).toString().trim().split('\n');
// const input = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n')
const [n,m] = input[0].split(' ').map(Number)
const arr = input[1].split(' ').map(Number)
let answer = 0;
const psum = new Array(n+1).fill(0)
arr.forEach((v,i)=>{
psum[i+1] = psum[i] + v
})
// console.log(psum)
const map = new Map();
psum.slice(1).forEach(v=>{
map.set(v%m,(map.get(v%m)||0)+1)
})
// console.log(map)
const check = [...map]
check.forEach(v=>{
answer+=(v[1]*(v[1]-1))/2
})
answer+=map.get(0)||0
console.log(answer)
반응형