반응형
수학적인 추론을 이끌어 내야 풀 수 있는 문제입니다.
'A(i) ~ A(j) = S(j) - S(i-1)' 가 Prefix Sum 의 기본 공식이고 나머지가 0 이어야 한다는 점에 착안해서 새로운 공식을 도출해야 합니다.
'A(1) ~ A(i) = K (K = 정수)' 이고 'A(1) ~ A(j) = K' 라면, 'A(i) ~ A(j) = 0' 이어야 합니다. 왜냐하면 i 부터 j 까지 합으로 인한 변화가 없어야 같은 K 가 나올 수 있기 때문입니다.
그리고 'A(i) ~ A(j) = 0' 이라면 양변에 나머지 연산을 해도 동일해서 '(A(i) ~ A(j)) % M = 0' 입니다.
이점에 착안해서 Prefix Sum 의 기본 공식을 대입하면 'A(i) ~ A(j) = S(j) - S(i-1) = 0' 이 성립합니다. 이를 다시 정리하면 아래와 같이 됩니다.
'S(j) = S(i-1)' 을 다시 적으면 'S(j) % M = S(i-1) % M'
위 공식이 성립하는 경우의 수가 문제가 요구하는 정답이므로, 부분 합의 나머지를 저장해놓고 동일한 나머지가 나타난 경우를 정답에 추가하여 출력합니다.
import sys
readline = sys.stdin.readline
read = sys.stdin.read
N, M = map(int, readline().split())
A = list(map(int, readline().split()))
A.insert(0,0)
P = [0] * (N + 1)
# 부분합 나머지가 나타난 횟수 저장
S = [0] * M
answer = 0
for i in range(1, N+1):
P[i] = (P[i-1] + A[i]) % M
# 부분합 비교가 아닌
# 1부터 i 까지 합의 나머지가 0 인 경우
if P[i] == 0:
answer += 1
# 부분합 나머지 등장 횟수 증가
S[P[i]] += 1
for j in range(M):
# 부분합 나머지 등장 횟수 C 2 (조합 계산) = 등장 횟수 * (등장 횟수 - 1) / 2
answer += (S[j] * (S[j] - 1)) // 2
print(answer)
코딩 테스트에서 이렇게 수학적인 생각을 하는건 어려울지도 모르겠네요...
반응형
'Develop > 코딩인터뷰' 카테고리의 다른 글
[코딩인터뷰] 2020 카카오 신입 공채 - 자물쇠와 열쇠 (0) | 2021.04.04 |
---|---|
[코딩인터뷰] 백준 2110번 공유기 설치 (0) | 2021.03.30 |
[코딩인터뷰] 백준 13398번 연속합 2 (0) | 2021.03.28 |
[코딩인터뷰] 백준 2616번 소형기관차 (0) | 2021.03.28 |
[코딩인터뷰] 백준 3020번 개똥벌레 (0) | 2021.03.28 |
꾸준히 노력하는 개발자 "김예건" 입니다.