[Python] BOJ 18291 - 비요뜨의 징검다리 건너기
18291번: 비요뜨의 징검다리 건너기
강을 건너는 방법은, (1 → 4), (1 → 2 → 4), (1 → 3 → 4), (1 → 2 → 3 → 4)의 4가지이다.
www.acmicpc.net
일단 N=1일 때부터 직접 계산해보면서 규칙을 찾아보았다.
N=1일 때 1, N=2일 때 1, N=3일 때 2, N=4일 때 4, N=5일 때 8 ...
N=1일 경우를 제외하고 2의 (N-2)제곱이 나오는 것을 확인 할 수 있었다.
단순히 print(2**(N-2))를 하면 N의 범위가 최대 10**9이므로 O(10**9)가 되어서 시간초과가 발생한다.
따라서 분할정복을 이용한 거듭제곱을 해서 시간을 줄여야 한다.
# 분할정복을 이용한 거듭제곱은 따로 정리해서 포스팅해놓았다: hbj0209.tistory.com/43
[Algorithm] 분할정복을 이용한 거듭제곱
# 분할정복을 이용한 거듭제곱 - C**n연산은 x를 n번 곱하므로 O(N)이지만, 이 방법을 사용하면 O(logN)에 거듭제곱 값을 구할 수 있다. - 아래 코드에서 fpow함수가 그 방법이다. - n이 1이면 그냥 C의 1
hbj0209.tistory.com
코드는 다음과 같다.
def pow(a,b): res = 1 while b: if b & 1: res *= a a = a*a b >>= 1 return res for _ in range(int(input())): N = int(input()) if N == 1: print(1) else: print(pow(2,N-2))
처음에 위와 같이 단순히 분할정복을 이용한 거듭제곱을 이용해 풀었는데도 시간초과가 떴다..
재귀로 해도 안되고 반복문으로 해도 안되서 헤매다가 10**9+7로 나누지 않고 있었다는 것을 깨달았다.
(문제 좀 제대로 읽자;;)
아래 코드와 같이 연산을 할 때마다 mod인 10**9+7로 나눠주면서 연산하니 통과가 되었다!
mod = 1000000007 def pow(a,b): res = 1 while b: if b & 1: res *= a res %= mod a = a*a b >>= 1 a %= mod return res for _ in range(int(input())): N = int(input()) if N == 1: print(1) else: print(pow(2,N-2))
(solved.ac 티어: 실버 1)
# 문제를 맞춘 뒤 고수들의 코드를 보니 Python은 그냥 내장함수 pow를 쓰면 통과가 된다. 배신감이 들었다...