백준 10986번 : 나머지 합 [Java]
문제
https://www.acmicpc.net/problem/10986
10986번: 나머지 합
수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오. 즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j)
www.acmicpc.net
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[] nums = new int[N + 1];
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= N; i++){ //배열 입력받기
nums[i] = Integer.parseInt(st.nextToken());
}
//구간합
int[] sum = new int[N + 1];
for(int i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + nums[i];
}
int result = 0;
/**
* sum[j] - sum[i - 1]
*/
for(int i = 1; i <= N; i++) {
for(int j = i; j <= N; j++) {
//System.out.println("("+i+", "+j+") : "+(sum[j] - sum[i - 1]));
if((sum[j] - sum[i - 1]) % M == 0) {
result++;
}
}
}
System.out.println(result);
}
}
처음에 그냥 단순히 구간합으로 돌렸더니 시간 초과가 떴다.
일단 원래 배열의 내용을 따로 저장할 필요도 없다는걸 깨달았다.
(A + B) % C = (A % C + B % C) % C라는 것을 이용하면
특정 구간 수들의 나머지 연산을 더해 나머지 연산을 한 값 = 이 구간 합의 나머지 연산을 한 값 이다.
S[]가 합을 M으로 나머지 연산을 한 결과일때
S[j] % M == S[i] % M 이라면
(S[j] - S[i]) % M은 0이다.
즉, S[j]와 S[i]가 같은 쌍을 찾으면 원본 배열에서 i + 1부터 j까지의 구간 합이 M으로 나누어 떨어진다는 것을 알 수 있다.
값이 같은 것들의 개수를 저장해두고
조합으로 개수를 계산 한 후 answer에 더한다.
그런데 자꾸 런타임에러가 나서 이유를 모르다가 long으로 바꾸니 해결이 됐다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
long[] sum = new long[N + 1];
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + Integer.parseInt(st.nextToken());
}
long answer = 0;
long[] count = new long[M + 1];
for(int i = 1; i <= N; i++) {
sum[i] = sum[i] % M;
int remainder = (int) sum[i];
if(remainder == 0) answer++;// (0, i)의 개수 세기
count[remainder]++; //나머지 개수 세기
}
for(int i = 0; i < M; i++) {
if(count[i] > 1) {
answer = answer + (count[i] * (count[i] - 1) / 2); //조합 계산
}
}
System.out.println(answer);
}
}
'문제풀이 > 코딩테스트' 카테고리의 다른 글
백준 2343번 : 기타 레슨 [Java] (0) | 2024.03.02 |
---|---|
SWEA [모의 SW 역량테스트] 미생물 격리 [Java] (1) | 2024.02.28 |
백준 1520번 : 내리막 길[Java] (0) | 2024.01.19 |
프로그래머스 기능개발 [Java] (0) | 2022.05.06 |
프로그래머스 멀쩡한 사각형 [Java] (0) | 2022.05.05 |