728x90
백준 32774번 문제는 solved.ac기준 플레티넘 4입니다.
월간 향유회의 운영진들은 각자 가지고 있는 공을 이용해 게임을 하려고 한다. 게임의 규칙과 목표는 다음과 같다:
- 각 운영진은 자신의 공을 모두 한 상자에 넣고 무작위로 섞는다.
- 상자에서 공을 하나씩 뽑으며, 같은 운영진의 공이 연속으로 뽑힐 때마다 해당 운영진은 1점을 얻는다.
- 게임은 여러 라운드로 진행되며, 각 라운드마다 참가하는 운영진의 범위가 주어진다.
이번 글에서는 모든 라운드가 끝난 후 각 운영진의 점수의 기댓값을 효율적으로 계산하는 방법을 소개한다.
1. 문제 이해하기
1.1 게임 규칙 요약
- 운영진 수: N명 (1≤N≤200,000)
- 각 운영진의 공의 수: A1,A2,…,AN(1≤Ai≤5,000)
- 라운드 수: Q개 (1≤Q≤200,000)
- 각 라운드의 참가자 범위: [li,ri]
1.2 목표
- 각 운영진이 얻는 점수의 기댓값 Ei를 계산한다.
- 기댓값은 분수 형태이며, 특정한 형식으로 출력해야 한다.
1.3 출력 형식
- 기댓값 가 기약분수 𝑝𝑖/𝑞𝑖일 때, 𝑝𝑖≡𝑞𝑖𝐸𝑖(mod10^9+7)을 만족하는 0≤pi<10^9+7인 정수를 출력한다.
2. 알고리즘 설계
2.1 각 라운드에서 운영진의 기대 점수 계산
한 라운드에서:
- 총 공의 수
- 운영진 i의 공의 수: S i =A i (단, 𝑙 𝑖 ≤ 𝑖 ≤ 𝑟 𝑖 인 경우)
운영진 i가 해당 라운드에서 얻는 기대 점수 Ei(round)는 다음과 같다:
2.2 전체 라운드에서의 기대 점수 합산
각 라운드의 기대 점수를 모두 합산하여 운영진별 총 기대 점수 를 계산한다.
2.3. 효율적인 계산을 위한 접근법
- 문제점: 각 라운드에서 모든 운영진에 대해 기대 점수를 계산하면 시간 복잡도가 O(NQ)로 너무 크다.
- 해결책: 누적합과 차분 배열을 활용하여 시간 복잡도를 O(N+Q)로 줄인다.
3. 코드 설계
3.1 필요한 계산 준비
3.1.1 공의 수 누적합 계산
- 목적: 특정 구간의 총 공의 수 T를 빠르게 계산하기 위함.
- 방법:
3.1.2 차분 배열을 이용한 구간 업데이트
- 목적: 각 운영진의 기대 점수에 대한 누적 기여도를 효율적으로 계산하기 위함.
- 방법:
- 배열 를 초기화한다.
- 각 라운드에서 [li,ri]구간에 대해 1/𝑇𝑖를 추가한다.
4. 백준 32764 울려퍼져라 문제 파이썬(python) 정답 코드
import sys
sys.setrecursionlimit(1 << 25)
MOD = 10 ** 9 + 7
def main():
import sys
input = sys.stdin.readline
N, Q = map(int, input().split())
A = list(map(int, input().split()))
# 공의 수 누적합 계산
prefix_A = [0] * (N + 1)
for i in range(N):
prefix_A[i + 1] = prefix_A[i] + A[i]
delta = [0] * (N + 2) # 차분 배열 초기화
for _ in range(Q):
l_i, r_i = map(int, input().split())
l_i -= 1 # 0-based index로 변환
T_i = prefix_A[r_i] - prefix_A[l_i] # 해당 라운드의 총 공의 수
if T_i == 0:
continue # 공이 없는 경우는 무시
inv_T_i = pow(T_i, MOD - 2, MOD) # 모듈러 역원 계산
delta[l_i] = (delta[l_i] + inv_T_i) % MOD
delta[r_i] = (delta[r_i] - inv_T_i + MOD) % MOD # 음수 방지
# 차분 배열로부터 각 운영진의 누적 기여도 계산
S = [0] * N
current = 0
for i in range(N):
current = (current + delta[i]) % MOD
S[i] = current
# 최종 기대 점수 계산
E = [0] * N
for i in range(N):
Ai = A[i]
if Ai >= 2:
Ai_Ai1 = Ai * (Ai - 1) % MOD
E[i] = Ai_Ai1 * S[i] % MOD
else:
E[i] = 0 # 공이 1개 이하인 경우 기대 점수는 0
# 결과 출력
print(' '.join(map(str, E)))
if __name__ == '__main__':
main()
5. 백준 32764 울려퍼져라 문제 파이썬(python) 제출 결과
도움이 되셨다면 공감과 댓글 부탁드립니다
728x90
'Python > 백준' 카테고리의 다른 글
백준 족보 검사하기 [32774] 파이썬(Python) 코드 + 해설 (1) | 2024.11.26 |
---|---|
백준 숫자 할당 [32825] 파이썬(Python) 코드 + 해설 (0) | 2024.11.25 |
백준 마법사 상어와 파이어볼[20056] 파이썬(Python) 코드 + 해설 (1) | 2024.11.24 |
백준 자석 체스[32334] 파이썬(Python) 코드 + 해설 (0) | 2024.11.23 |
백준 하모니[32338] 파이썬(Python) 코드 + 해설 (0) | 2024.11.22 |