2023. 4. 30. 22:56ㆍ_Study/Baekjoon
백준 문제풀이 | python | ||
No. 10986 나머지 합 구하기 |
#python #백준 #문제풀이 #10986 나머지 합 구하기
https://www.acmicpc.net/problem/10986
10986번: 나머지 합
수 N개 A1, A2, ..., AN이 주어진다. 이때, 연속된 부분 구간의 합이 M으로 나누어 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오. 즉, Ai + ... + Aj (i ≤ j) 의 합이 M으로 나누어 떨어지는 (i, j)
www.acmicpc.net
예제 입력 1
5 3
1 2 3 1 2
예제 출력 1
7
이번 글에서는 구간의 합으로 나누는 법을 구현하는데 중점을 둔다. (A+B) %C 는 (A%C)+(B%C)) %C 와 같다.
// 알고리즘
가장 중요한 목적이 무엇인지?
구간의 합으로 계산하려면 어떻게 해야하는지?
예시로
5 3
1 2 3 1 2
입력 값이 들어오고 3으로 나누어 떨어지는 쌍을 나누었더니 7개가 나온다.
여기서 i<=j 이므로 하나도 포함.
(1,2)[0.1] (1,2,3)[0,2] (1,2,3,1,2)[0,4]
(2,3,1) [1,3]
(3) [2]
(3,1,2) [2,4]
(1,2) [3,4]
이런식이므로, 일단 더해가면서 어라? 이게 안 나눠떨어지네 하면 가차없이 다음 정렬로 돌리면 된다.
왠지 N이 10^6이라서 1초를 넘는 시간 복잡도가 걸릴 거 같지만 (logN^2이면 100초가 걸린다고 하는데)
좋은 방법이 있을까?
부분합을 모두 구해두고.
적절하게 빼주었을때, 어떻게 빼야 부분합이 나누어 떨어질까?
부분합이 배수로 애초에 나뉜다면?
[1, 3, 6, 7, 9]
3,6,9 가 되겠다. 이는 [0:]에서 이어진 경우.
7-1=6 이 되겠다 이는 [1:3]인 경우.
버블 정렬로 빼면 나오게 된다. 버블정렬 써도 되나?
암튼 해본다.
역시 시간초과
(A+B) %C 는 (A%C)+(B%C)) %C 와 같다. 는 아이디어가 중요하다.
해당 부분합들을 %M 으로 나누면 0이면. 나뉘어서 계산되는 것이다. 더해서 M이되면? 역시 계산 되는 것이다.
[1, 0, 0, 1, 0]
그리고 부분합이 같은 값 을 골라서 빼면 0이 나오므로 조합을 구하면 된다.
index 0과, index 4의 1을 빼면 어떤 결과인지 알아보자.
index 0 의 값은 1
index 3의 값은 1,2,3,1 의 값이다. 어차피 나머지 연산이라 뒤의 값이 사라지고 중복값을 빼준것. 따라서 [1:3]
왜 이런 방법을 선택했는지?
// 계획하기
함수명 | 설명 | ||
1. | |||
2. | |||
3. |
// 구현하기
-> How?
어떻게 구현?
첫째 줄에 N과 M이 주어진다.
그리고 M의 합으로 나누어 떨어지는 쌍의 개수를 구해야한다.
->Why?
왜 이런 방법을?
// 수정하기
import sys
input = sys.stdin.readline
N, M = map(int,input().split())
numbers = list(map(int, input().split()))
prefix_sum = []
temp = 0
cnt = 0
for i in numbers:
temp = temp+i
prefix_sum.append(temp)
if(temp%M == 0): cnt+=1
# for i in range(M):
# print(prefix_sum[e] - prefix_sum[s-1])
#print(prefix_sum)
for i in range(len(prefix_sum)):
for j in range(len(prefix_sum)-1,i,-1):
if (prefix_sum[j]-prefix_sum[i]) % M == 0:
cnt+=1
print(cnt)
버블 정렬이라 시간초과, 저기서 temp%M ==0 저기서 아이디어를 얻었어야 했다.
// 완성코드
import sys
input = sys.stdin.readline
N, M = map(int,input().split())
numbers = list(map(int, input().split()))
prefix_sum = []
remainder = [0]*M
temp = 0
cnt = 0
for i in numbers:
temp = (temp+i)%M
if(temp == 0): cnt+=1
prefix_sum.append(temp)
remainder[temp] += 1
for i in range(M):
if remainder[i]>1:
cnt += (remainder[i]*(remainder[i]-1) //2)
print(cnt)
'_Study > Baekjoon' 카테고리의 다른 글
[11003] 최솟값 찾기 #파이썬 (0) | 2023.05.01 |
---|---|
[BOJ:1253] 좋다 #파이썬 #백준 (0) | 2023.05.01 |
[11659] 백준 구간 합 구하기 1 python (0) | 2023.04.25 |
[11004] K번째 수 #파이썬 #백준 #퀵정렬 (0) | 2023.04.04 |
프로그래머스 숨어있는 숫자의 덧셈 (2) 파이썬 테스트 2,3,4,5,6,7 실패 해결 (0) | 2023.04.03 |