코팅테스트/백준 문제 모음
백준 24956번 파이썬 문제풀이(나는 정말 휘파람을 못 불어)
유지광이
2022. 5. 2. 22:09
728x90
https://www.acmicpc.net/problem/24956
24956번: 나는 정말 휘파람을 못 불어
'유사 휘파람 문자열'인 부분 수열의 개수를 $1\,000\,000\,007(= 10^9+7)$로 나눈 나머지를 출력한다.
www.acmicpc.net
이 문제 사실 골드 4 치고는 굉장히 어려운 문제이다. 접근 방법은 다음과 같다.
1. 누적합으로 W와 E의 개수를 미리 구해야 놓아야 한다. (단 E는 반대방향으로 누적합)
2. H를 만날때 마다 해당 H지점에서 왼쪽으로 W의 개수 * 2 ^ 오른쪽으로 E의 개수 - E의개수 - 1 로 구해야한다.
3. pow 내장 메서드와 3번 째인자 Mod 사용하면 더욱더 빠른 시간복잡도로 2 ** N 계산이 가능하다.
여기서 의문인 2 ^ 오른쪽으로 E의 개수 - E의개수 - 1 식이 왜 나오는지를 알아야한다. 반대로 말하면 EC2 + EC3 + EC4 + ... ECE 까지의 합을 구해야하는데 결국 이는 전체의 부분집합 2 ^ E 에서 EC1 , EC0 일때 즉 1개를 뽑을 때와 0개를 뽑을 때를 빼주어야 하는 것과 동치이다.
N = int(input())
word = input()
W_acc = [0] * N
E_acc = [0] * N
W_acc[0] = int(word[0] == 'W')
E_acc[-1] = int(word[-1] == 'E')
# 각각의 방향으로 W, E의 누적합 개수 구하기
idx = N - 2
for i in range(1, N):
W_acc[i] = W_acc[i - 1] + int(word[i] == 'W')
E_acc[idx] = E_acc[idx + 1] + int(word[idx] == 'E')
idx -= 1
ans = 0
for i in range(N):
# H을 만날때마다 계산해주기
if word[i] == 'H':
ans += (W_acc[i] * (pow(2, E_acc[i], 1000000007) - E_acc[i] - 1))
print(ans % 1000000007)
728x90