[문제]
https://www.acmicpc.net/problem/10986
[풀이]
문제에서 생각해야 할 부분은 크게 2가지이다.
1. 인덱스 0부터 i 까지의 누적 합, 즉 sum[i]에 modulo 연산을 취했을 때 값이 0이라면, M으로 나누어 떨어지는 수이다. cnt[] 배열을 증가시켜줌으로써 개수를 구할 수 있다.
2. 특정 인덱스 i 부터 j 까지의 누적 합에 대해서도 M으로 나누어떨어지는지 확인이 필요하다.
이는 (sum[j] - sum[i]) % m = 0 (i<=j)인지 묻는 것이고, sum[j] % m = sum[i] % m 과 같이 나타낼 수 있다.
예를 들어 시작 인덱스가 1이고, 1, 4, 6, 7에 대해 m으로 나눈 나머지 값이 같다면, 이는 곧 1~4, 1~6, 1~7, 4~6, 4~7, 6~7 의 범위의 누적 합이 m으로 나누어 떨어진다는 뜻이다. 따라서 이에 대한 개수는 nC2로 알아낼 수 있다.
이 문제에서 또 한가지 주의할 점은 수의 범위이다. 처음, Ai<=10^9 이므로 sum은 long long으로 선언했지만 N이 최대 10^6이기에 cnt 배열은 int로 선언을 하였다. 그런데 cnt 배열도 long long으로 선언해야 통과가 되길래 의아했는데, cnt[i]*(cnt[i]-1) / 2 부분에서 계산 결과가 int 범위를 넘을 수 있다..! 따라서 애초에 cnt 배열을 long long으로 선언하거나 (long long) cnt[i]*(cnt[i]-1) / 2 과 같이 캐스팅을 해줘야 한다!
[코드]
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <stack>
#define INF 987654321
using namespace std;
int n, m;
long long sum;
int cnt[1001];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
int temp;
for (int i = 0; i < n; i++) {
cin >> temp;
sum += temp;
cnt[sum % m]++;
}
long long result = cnt[0];
//nC2
for(int i=0; i<m; i++){
result += (long long)cnt[i]*(cnt[i]-1) / 2;
}
cout << result;
}
'알고리즘 공부 및 문제 풀이 > 백준(BOJ)' 카테고리의 다른 글
[boj] 백준 1613 역사 (c++) - 플로이드-와샬 (0) | 2022.11.28 |
---|---|
[boj] 백준 2473 세 용액 (c++) - 투 포인터 (0) | 2022.11.24 |
[boj] 백준 2629 양팔저울 (c++) - dp, 재귀 (1) | 2022.11.22 |
[boj] 백준 10159 저울 (c++) - 플로이드-와샬 (0) | 2022.11.17 |
[boj] 백준 16637 괄호 추가하기 (c++) - dfs, 브루트포스 (0) | 2022.11.16 |