기록 보관소

[Baekjoon/백준] 10986번: 나머지 합(C/C++) 본문

코딩 테스트/백준

[Baekjoon/백준] 10986번: 나머지 합(C/C++)

JongHoon 2022. 7. 5. 19:35

단계별로 풀어보기 17단계(누적 합) 4번 문제

https://www.acmicpc.net/step/48

 

누적 합 단계

구간 합의 아이디어를 응용하여 특정 조건을 만족하는 구간의 개수를 구하는 문제

www.acmicpc.net


백준 10986번: 나머지 합

https://www.acmicpc.net/problem/10986

 

10986번: 나머지 합

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

www.acmicpc.net


문제 설명

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

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


입력과 출력

입력: 첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 10^6, 2 ≤ M ≤ 10^3)

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

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


접근 방법

이번 문제는 배열 A의 숫자 개수 N과 나눌 숫자 M을 입력받고 N개의 숫자를 입력해서 해당 숫자들을 연속해서 더 했을 때 M으로 나누어 떨어지는 구간 개수를 출력하는 문제다.

1 2 3 1 2
1 2 3 1 2
1 2 3 1 2
1 2 3 1 2
1 2 3 1 2
1 2 3 1 2
1 2 3 1 2

예제를 통해서 보면 위 표처럼 [1, 2], [1, 2, 3], [1, 2, 3, 1, 2], [2, 3, 1], [3], [3, 1, 2], [1, 2]의 연속되는 구간 7개가 3으로 나누어 떨어지므로  7이 출력되는 것이다.

우선 위 표를 보고 간단하게 생각하면 누적 합을 이용해서 처음부터 계속 누적해가면서 M으로 나눈 나머지가 0인 것의 개수만 세면 되는 것 처럼 보인다.

하지만 그렇게 하면 앞의 [1, 2], [1, 2, 3], [1, 2, 3, 1, 2]의 연산만 해서 3을 출력하게 될 것이다.

이를 위해서 추가적으로 nC2, 그러니까 조합 연산이 추가되어야 한다.

개인적으로 이 마지막 조합 연산 부분을 생각하지 못해 막혀서 여러 블로그들을 참고해서 문제 풀이를 진행했다. 역시 수학은 힘들다..


코드

#include <iostream>
using namespace std;
#define MAX 1000001

long long A[MAX];
long long sum[MAX];

int main(int argc, char * argv[]) {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	long long count = 0;
	int N, M;
	cin >> N >> M;

	sum[0] = 0;
	for (int i = 1; i <= N; i++) {
		int num;
		cin >> num;

		sum[i] = (sum[i - 1] + num) % M;
		if (sum[i] == 0)
			count++;

		A[sum[i]]++;
	}

	for (int i = 0; i < M; i++)
		count += A[i] * (A[i] - 1) / 2;

	cout << count << endl;

	return 0;
}

결과

백준 제출 결과

배열 크기만이 아닌 입력되는 값도 10^6이라서 int를 쓰면 안되는데 썼다가 틀렸다.