※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 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 |