티스토리 뷰
나머지 합 성공
1 초 | 256 MB | 19410 | 5786 | 4234 | 28.212% |
문제
수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오.
즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j) 쌍의 개수를 구해야 한다.
입력
첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 106, 2 ≤ M ≤ 103)
둘째 줄에 N개의 수 A1, A2, ..., AN이 주어진다. (0 ≤ Ai ≤ 109)
출력
첫째 줄에 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 출력한다.
예제 입력 1 복사
5 3
1 2 3 1 2
예제 출력 1 복사
7
#include <iostream>
using namespace std;
long arr[1005001], C[1005001] = { 0 }, S[1005001];
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m, rema;
long cnt = 0;
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
S[0] = arr[0];
for (int i = 1; i < n; i++)
{
S[i] = S[i - 1] + arr[i];
}
for (int i = 0; i < n; i++)
{
rema = S[i] % m;
if (rema == 0)
cnt++;
C[rema]++;
}
for (int i = 0; i < m; i++)
cnt += (C[i] * (C[i] - 1)) / 2;
printf("%ld", cnt);
return 0;
}
각 구간의 합이 받은 값 m으로 나누어지는지 확인하는 문제다.
예제에서
1 2 3 1 2를 받고 이것의 구간합이 3으로 나누어지는지 확인해보자.
우선 이를 일일이 계산해보면
1
1+2
1+2+3
1+2+3+1
1+2+3+1+2
2
2+3
2+3+1
2+3+1+2
3
3+1
3+1+2
등등이 m(=3)으로 나누어지는지 확인해야 한다. 그러나 이는 시간이 너무 오래걸리기에 단축하는 방법이 필요하다.
여기서 우리는 (A+B) % C = ((A %C) + (B %C)) %C 의 공식을 이용하기로 하자.
예를 들어 7 %2 =1 이다. 3 %2 =1 이다.
(7 + 3) % 2 = 0 = (1 +1) %2 가 된다.
각각의 나머지가 더해지기 때문에 결국 같게 된다.
이 논리를 이용하여 문제를 풀자.
1) 각각의 구간합 구하기
입력
1 | 2 | 3 | 1 | 2 |
구간합
1 | 3 | 6 | 7 | 9 |
위의 구간합을 보면 각각의 구간합은
1
1+2
1+2+3
1+2+3+1
1+2+3+1+2
이를 의미한다.
이 값을 M으로 나누어 떨어진다면 1부터 시작하는 구간합이 나누어 떨어지는지를 구할 수 있다.
1 | 0 | 0 | 1 | 0 |
0으로 된 부분은 나누어 떨어진 부분이고, 1로 된 부분은 나누어 떨이지지 않는 부분이다.
그렇다면 여기서 다시 2부터 계산을 한다면 시간이 오래걸린다.
그렇기에 위에 설명한 공식, (A+B) % C = ((A %C) + (B %C)) %C 에 따라 이를 계산한다.
나머지가 1인 구간끼리 빼면 나머지만큼 빼지기 때문에 이 부분은 나누어진다.
예를 들면 7%2 =1 이고, 3%2=1이다.
그럼 7-3 =4가 됨으로 나머지가 0이된다.
나머지가 0인 부분에서도 마찬가지이다.
나머지가 0인 부분은 3개니까, 그 갯수는 3C2가 된다.
인덱스가 1,2,4가 0이라고 하면
(인덱스 4-2) -1
(인덱스 4-1) - 2
(인덱스 2-1) - 3
총 3개의 경우의 수가 나온다.
또한 2C2를 통해 1인 것들의 갯수를 구할 수 있다.
이를 기존의 값에 추가해주면 문제를 풀 수 있다.
'프로그래밍 > 백준 문제풀이' 카테고리의 다른 글
백준 1940 주몽 C/C++ (0) | 2023.01.07 |
---|---|
백준 2018 수들의 합 C/C++ (0) | 2023.01.07 |
백준 11660 구간 합 구하기5 C/C++ (0) | 2023.01.05 |
백준 11659 구간 합 구하기 C/C++ (0) | 2023.01.05 |
백준 10090 counting inversions C/C++ (0) | 2022.12.16 |
- Total
- Today
- Yesterday
- 티스토리챌린지
- 류근관
- 인프런
- 윤성우
- 백준
- 회계
- 일본어문법무작정따라하기
- 정보처리기사
- 일문따
- 심리학
- C/C++
- 통계
- 뇌와행동의기초
- stl
- 데이터분석
- 인지부조화
- K-MOOC
- 여인권
- 보세사
- Python
- 열혈프로그래밍
- 사회심리학
- 일본어
- 강화학습
- C
- 통계학
- 오블완
- 파이썬
- c++
- 코딩테스트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |