누적 합
누적 합
백준 10986 나머지합 문제풀이
굉장히 오랜만에 블로그로 돌아왔다. 폐관수련 중이였다. 백준티어도 골드2정도로 올렸고 여러가지 자료구조들과 알고리즘들을 익혔다.
이제 본격적으로 포스팅도 해가며 공부를 할 계획이다. 이제 백준 플레티넘과 코드포스 블루를 향해 달려보도록 하겠다.
이후에 고수가 된다면 공부방법도 포스팅해봐야지 그 시작으로 누적합관련 문제..
백준 10986 나머지 합을 풀어보도록 하자 10986 나머지 합.
문제상황 파악하기.
나머지 연산(moduler 연산)에 관련되어있고 누적합을 이용하여 시간 복잡도를 줄여야한다.
for문을 두번 써서 계산하면 O(N^2)의 시간 복잡도를 가지는데 N이 최대 1000000이므로 이문제는 O(N)으로 풀어야한다.
그러면 자연스럽게 누적합을 써야겠단 생각이든다.
아이디어 얻기.
(A+B)mod m = A mod m + B mod m.
(A-B)mod m = A mod m - B mod m moduler연산에서 성립한다.
그러므로 모든 누적합들을 미리 m으로 나누어둬도 상관없다.
그러면 누적합을 구하고 맨 같은 수가 몇개인지 센후 이항계수를 다 더해주면 정답이 될것이다.
주의할 점.
그렇다면 정답의 최댓값은 무엇이 될까 이항계수 binomal(1000001,2)가 최대가 될것이고 이 값은 int범위를 넘어간다.
그러니 답은 long long 형으로 해주기로 하자.
하지만 연산 과정에 int가 있으면 int로 바꾸니 모든 변수를 long long으로 바꿔주겠다.
실제 코드.
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
32
33
34
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
long long cumsum[1000001]; //누적합 저장
long long modrlt[1001]; // 나머지가 몇개인지 카운트
int main(){
cin.tie(NULL);
cout.tie(NULL);
ios_base::sync_with_stdio(false);
int n,m;
cin >> n >> m;
cumsum[0] = 0;
modrlt[0]++;
for(int i=1;i<=n;i++){
long long num;
cin >> num;
cumsum[i] = cumsum[i-1] + num;
modrlt[cumsum[i]%m]++;
}
long long result=0;
for(int i=0;i<1001;i++){
result += modrlt[i]*(modrlt[i]-1)/2;
}
cout << result;
}
This post is licensed under CC BY 4.0 by the author.
