※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 10986번 문제인 나머지 합이다.
문제는 아래 링크를 확인하자.

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

 

10986번: 나머지 합

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

www.acmicpc.net

첫 번째 원소부터 k번째 원소까지의 합을 f(k)로 나타내자.

 

L번째 원소부터 R번째 원소까지의 연속된 부분구간의 합은 f(R)-f(L-1)로 나타낼 수 있다는 것을 관찰하자.

 

이때, L번째 원소부터 R번째 원소까지의 합이 M의 배수라는 것은 f(R)과 f(L-1)을 각각 M으로 나눈 나머지가 동일하다는 것과 동치라는 것을 발견하면, 같은 나머지를 갖는 f(k)들의 게수를 세어 L-1과 R의 쌍을 세는 것으로 문제를 해결할 수 있다.

 

이때, f(k) 그 자체도 하나의 구간합이 된다는 점을 잊지 말자. 글쓴이는 f(0) = 0의 값을 하나 더하는 것으로 이를 확인해주었다.

 

답이 일반적인 32비트 정수형으로 표현할 수 없을 수 있다는 점을 유의하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
using namespace std;
typedef long long ll;

ll cnt[1000];

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cnt[0] = 1;
	int temp = 0;
	int N, M; cin >> N >> M;
	while (N--) {
		int x; cin >> x;
		temp = (temp + x) % M;
		cnt[temp]++;
	}
	ll ans = 0;
	for (int i = 0; i < M; i++) {
		ans += cnt[i] * (cnt[i] - 1) / 2;
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 5639 // C++] 이진 검색 트리  (0) 2021.11.23
[BOJ 15353 // C++] 큰 수 A+B (2)  (0) 2021.11.22
[BOJ 16532 // C++] Looking for the Risk Factor  (0) 2021.11.20
[BOJ 17425 // C++] 약수의 합  (0) 2021.11.19
[BOJ 9359 // C++] 서로소  (0) 2021.11.18

+ Recent posts