일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 밑바닥부터 시작하는 딥러닝
- Backtracking
- overfiting
- jini impurity
- deep learning
- Python
- do it! 알고리즘 코딩테스트: c++편
- word2vec
- 고전소설
- Baekjoon
- BFS
- classification
- C++
- model selection
- 딥러닝
- DFS
- tree purning
- marchine learning
- Language model
- CBOW
- boosting for classification
- Linear Regression
- 밑바닥부터 시작하는 딥러닝2
- Machine Learning
- underfiting
- numpy
- RNN
- SQLD
- boosting for regression
- dynamic programming
- Today
- Total
newhaneul
[Do it! 알고리즘 코딩테스트: Chapter 3] 누적 합(Prefix Sum) 본문
본 포스팅은 Do it! 알고리즘 코딩테스트: C++편을 토대로 공부한 내용을 정리하기 위한 포스팅입니다.
https://github.com/KwonKiHyeok/Do_it_Alogrithm_Coding_Test_with_Cpp
GitHub - KwonKiHyeok/Do_it_Alogrithm_Coding_Test_with_Cpp: Do it! 알고리즘 코딩 테스트: C++편
Do it! 알고리즘 코딩 테스트: C++편. Contribute to KwonKiHyeok/Do_it_Alogrithm_Coding_Test_with_Cpp development by creating an account on GitHub.
github.com
누적 합(Prefix Sum)
브루트 포스를 개선하기 위해 미리 누적된 합을 저장해놓고 활용하는 기법이다.
즉, S[i]는 1번부터 i번까지의 합을 의미이다.
위 공식을 사용하면 O(1) 시간에 구간 합을 구할 수 있다.
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, M, A;
cin >> N >> M;
vector<vector<int>> arr(N+1, vector<int>(N+1, 0));
for (int j = 1; j <= N; j++) {
for (int i = 1; i <= N; i++) {
cin >> A;
arr[j][i] = A + arr[j-1][i] + arr[j][i-1] - arr[j-1][i-1];
}
}
for (int i = 0; i < M; i++) {
int x1, y1, x2, y2, sum = 0;
cin >> x1 >> y1 >> x2 >> y2;
sum = arr[x2][y2] - arr[x1-1][y2] - arr[x2][y1-1] + arr[x1-1][y1-1];
cout << sum << '\n';
}
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N, M, A;
cin >> N >> M;
vector<long> C(M, 0);
vector<long> arr(N, 0);
cin >> arr[0];
for (int j = 1; j < N; j++) {
cin >> A;
arr[j] = (arr[j - 1] + A);
}
long sum = 0;
for (int i = 0; i < N; i++) {
int remainder = arr[i] % M;
if (remainder == 0) {
sum++;
}
C[remainder]++;
}
for (int i = 0; i < M; i++) {
if (C[i] > 1) {
sum += C[i] * (C[i] - 1) / 2;
}
}
cout << sum << '\n';
return 0;
}
난이도가 있는 누적 합 알고리즘 문제였다. 이 문제의 핵심 아이디어는 '(A + B) % C는 ((A % C) + (B % C)) % C와 같다'이다. 특정 구간 수들의 나머지 연산을 더해 나머지 연산을 한 값과 이 구간 합의 나머지 연산을 한 값은 동일하다. 또한, S[j] % M의 값과 S[i] % M의 값이 같다면 (S[j] - S[i]) % M은 0이다. 즉, 구간 합 배열의 원소를 M으로 나눈 나머지로 업데이트하고 S[j]와 S[i]가 같은 (i, j)쌍을 찾으면 원본 배열에서 i + 1부터 j까지의 구간 합이 M으로 나누어떨어진다는 것을 알 수 있다. 따라서 같은 나머지를 가진 수들 중에서 2개를 선택하는 경우의 수를 구하기 위해 Combination을 진행하여 합을 구해 문제를 해결한다.
'1. Programming > Alogrithm' 카테고리의 다른 글
[Do it! 알고리즘 코딩테스트: Chapter 4] 버블 정렬(Bubble Sort), 선택 정렬(Selection sort) (0) | 2025.03.06 |
---|---|
[Do it! 알고리즘 코딩테스트: Chapter 3] 스택과 큐(Stack and Queue) (0) | 2025.03.05 |
[Do it! 알고리즘 코딩테스트: Chapter 3] 슬라이딩 윈도우(Sliding Window) (0) | 2025.03.04 |
[Do it! 알고리즘 코딩테스트: Chapter 3] 투 포인터 알고리즘(Two Pointer Algorithm) (0) | 2025.03.04 |
[Do it! 알고리즘 코딩테스트: Chapter 3] 배열과 리스트 그리고 벡터 (0) | 2025.03.04 |