[백준] 11444번 피보나치 수6

[백준] 11444번 피보나치 수6

출처: [백준] 11444번 피보나치 수6


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 3363 1774 1450 57.494%

문제

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다.

이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가 된다.

n=17일때 까지 피보나치 수를 써보면 다음과 같다.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597

n이 주어졌을 때, n번째 피보나치 수를 구하는 프로그램을 작성하시오.


입력

첫째 줄에 n이 주어진다. n은 1,000,000,000,000,000,000보다 작거나 같은 자연수이다.


출력

첫째 줄에 n번째 피보나치 수를 1,000,000,007으로 나눈 나머지를 출력한다.


예제 입력 1

1
1000

예제 출력 1

1
517691607

힌트


출처


알고리즘 분류


풀이


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import sys

input = sys.stdin.readline

N = int(input())
mod = 1000000007
fibo = {}


def fibo_dp(n):
if n <= 1:
return n
elif fibo.get(n):
return fibo[n]
else:
if n % 2 == 1: # 홀수
m = (n + 1) // 2
temp1 = fibo_dp(m)
temp2 = fibo_dp(m - 1)
fibo[n] = temp1 ** 2 + temp2 ** 2
fibo[n] %= mod
return fibo[n]
else: # 짝수
m = n // 2
temp1 = fibo_dp(m - 1)
temp2 = fibo_dp(m)
fibo[n] = (2 * temp1 + temp2) * temp2
fibo[n] %= mod
return fibo[n]


print(fibo_dp(N))


[백준] 2749번 피보나치 수3

[백준] 2749번 피보나치 수3

출처: [백준] 2749번 피보나치 수3


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 128 MB 17482 5649 4570 38.230%

문제

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다.

이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가 된다.

n=17일때 까지 피보나치 수를 써보면 다음과 같다.

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597

n이 주어졌을 때, n번째 피보나치 수를 구하는 프로그램을 작성하시오.


입력

첫째 줄에 n이 주어진다. n은 1,000,000,000,000,000,000보다 작거나 같은 자연수이다.


출력

첫째 줄에 n번째 피보나치 수를 1,000,000으로 나눈 나머지를 출력한다.


예제 입력 1

1
1000

예제 출력 1

1
228875

힌트

  • 피사노 주기

출처


알고리즘 분류


비슷한 문제


풀이


소스코드 1 (반복문을 이용한 다이나믹 프로그래밍)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sys

input = sys.stdin.readline

mod = 1000000
p = int(mod / 10 * 15) # 피사노주기에 의해 M = 10^k 일 때, k > 2 라면, 주기는 항상 15 × 10^(k-1) 입니다
fibo = [0] * p
fibo[1] = 1

N = int(input())

for i in range(2, p):
fibo[i] = fibo[i - 1] + fibo[i - 2]
fibo[i] %= mod

print(fibo[N % p])

[백준] 10830번 행렬제곱

[백준] 10830번 행렬제곱

출처: [백준] 2740번 행렬곱셈


시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 10162 3490 2817 34.179%

문제

크기가 N x N인 행렬 A가 주어진다. 이때, A의 B제곱을 구하는 프로그램을 작성하시오. 수가 매우 커질 수 있으니, A^B의 각 원소를 1,000으로 나눈 나머지를 출력한다.


입력

첫째 줄에 행렬의 크기 N과 B가 주어진다. (2 ≤ N ≤ 5, 1 ≤ B ≤ 100,000,000,000)

둘째 줄부터 N개의 줄에 행렬의 각 원소가 주어진다. 행렬의 각 원소는 1,000보다 작거나 같은 자연수 또는 0이다.


출력

첫째 줄부터 N개의 줄에 걸쳐 행렬 A를 B제곱한 결과를 출력한다.


예제 입력 1

1
2
3
2 5
1 2
3 4

예제 출력 1

1
2
69 558
337 406

예제 입력 2

1
2
3
4
3 3
1 2 3
4 5 6
7 8 9

예제 출력 2

1
2
3
468 576 684
62 305 548
656 34 412

예제 입력 3

1
2
3
4
5
6
5 10
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1

예제 출력 3

1
2
3
4
5
512 0 0 0 512
512 0 0 0 512
512 0 0 0 512
512 0 0 0 512
512 0 0 0 512

힌트


출처


알고리즘 분류


시간 제한


풀이


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import sys

input = sys.stdin.readline

N, B = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(N)]


def matrix_multiple(a, b):
if b == 1:
for i in range(N):
for j in range(N):
a[i][j] %= 1000
return a
else:
if b % 2 == 0: # 제곱수가 짝수일 때 AAAAAA --> (A^2)^2^2
temp_matrix = [[0 for _ in range(N)] for _ in range(N)]
c = matrix_multiple(a, b // 2)
for i in range(N):
for j in range(N):
for k in range(N):
temp_matrix[i][j] += c[i][k] * c[k][j]
temp_matrix[i][j] %= 1000
return temp_matrix

else: # AAAAA --> (A^2)^2 * A
temp_matrix = [[0 for _ in range(N)] for _ in range(N)]
c = matrix_multiple(a, b - 1)
for i in range(N):
for j in range(N):
for k in range(N):
temp_matrix[i][j] += c[i][k] * a[k][j]
temp_matrix[i][j] %= 1000
return temp_matrix


result = matrix_multiple(matrix, B)
for row in result:
for value in row:
print(value, end=" ")
print()

!!![백준] 11401번 이항 계수3

!!![백준] 11401번 이항 계수3

출처: [백준] 11401번 이항 계수3


문제

자연수 N과 정수 K가 주어졌을 때 이항 계수를 1,000,000,007로 나눈 나머지를 구하는 프로그램을 작성하시오.


입력

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 4,000,000, 0 ≤ K ≤ N)


출력

를 1,000,000,007로 나눈 나머지를 출력한다.


예제 입력 1

1
5 2

예제 출력 1

1
10

힌트

  • 페르마의 소정리 이용

출처


알고리즘 분류


시간 제한


풀이


소스코드 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import sys

input = sys.stdin.readline

N, K = map(int, input().split())
mod = 1000000007


def power(a, b):
if b == 0:
return 1
else:
if b % 2 == 0: # B가 짝수일 때
return (power(a, b // 2) ** 2) % mod
else:
return (power(a, b // 2) ** 2 * a) % mod


# Factorial dp
fact = [1 for _ in range(N + 1)]

for i in range(2, N + 1):
fact[i] = fact[i - 1] * i % mod

child = fact[N]
parent = (fact[K] * fact[N - K]) % mod

# 페르마의 소정리
print((child % mod) * (power(parent, mod - 2) % mod) % mod)

# -------------------------------------------------
# for i in range(2, N + 1):
# fact[i] = fact[i - 1] * i
#
# child = fact[N]
# parent = fact[K] * fact[N - K]

# print(int(child / parent) % mod) ==> 메모리초과

[백준] 1629번 곱셈

[백준] 1629번 곱셈

출처: [백준] 1629번 곱셈


문제

자연수 A를 B번 곱한 수를 알고 싶다. 단 구하려는 수가 매우 커질 수 있으므로 이를 C로 나눈 나머지를 구하는 프로그램을 작성하시오.


입력

첫째 줄에 A, B, C가 빈 칸을 사이에 두고 순서대로 주어진다. A, B, C는 모두 2,147,483,647 이하의 자연수이다.


출력

첫째 줄에 A를 B번 곱한 수를 C로 나눈 나머지를 출력한다.


예제 입력 1

1
10 11 12

예제 출력 1

1
4

힌트


출처


알고리즘 분류


시간 제한


풀이


소스코드 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sys

input = sys.stdin.readline


def power(a, b):
if b == 1:
return a % C
else:
if b % 2 == 0: # B가 짝수일 때
return power(a, b // 2) ** 2 % C
else:
return power(a, b // 2) ** 2 * a % C


A, B, C = map(int, input().split())
print(power(A, B))

소스코드 2

1
2
3
4
5
6
7
import sys

input = sys.stdin.readline

A, B, C = map(int, input().split())
print(pow(A, B, C))

[백준] 1780번 종이의 개수

[백준] 1780번 종이의 개수

출처: [백준] 1780번 종이의 개수


문제

N×N크기의 행렬로 표현되는 종이가 있다. 종이의 각 칸에는 -1, 0, 1의 세 값 중 하나가 저장되어 있다. 우리는 이 행렬을 적절한 크기로 자르려고 하는데, 이때 다음의 규칙에 따라 자르려고 한다.

  1. 만약 종이가 모두 같은 수로 되어 있다면 이 종이를 그대로 사용한다.
  2. (1)이 아닌 경우에는 종이를 같은 크기의 9개의 종이로 자르고, 각각의 잘린 종이에 대해서 (1)의 과정을 반복한다.

이와 같이 종이를 잘랐을 때, -1로만 채워진 종이의 개수, 0으로만 채워진 종이의 개수, 1로만 채워진 종이의 개수를 구해내는 프로그램을 작성하시오.입력

첫째 줄에는 영상의 크기를 나타내는 숫자 N 이 주어진다. N 은 언제나 2의 제곱수로 주어지며, 1 ≤ N ≤ 64의 범위를 가진다. 두 번째 줄부터는 길이 N의 문자열이 N개 들어온다. 각 문자열은 0 또는 1의 숫자로 이루어져 있으며, 영상의 각 점들을 나타낸다.


입력

첫째 줄에 N(1 ≤ N ≤ 37, N은 3k 꼴)이 주어진다. 다음 N개의 줄에는 N개의 정수로 행렬이 주어진다.


출력

첫째 줄에 -1로만 채워진 종이의 개수를, 둘째 줄에 0으로만 채워진 종이의 개수를, 셋째 줄에 1로만 채워진 종이의 개수를 출력한다.


예제 입력 1

1
2
3
4
5
6
7
8
9
10
9
0 0 0 1 1 1 -1 -1 -1
0 0 0 1 1 1 -1 -1 -1
0 0 0 1 1 1 -1 -1 -1
1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0
0 1 -1 0 1 -1 0 1 -1
0 -1 1 0 1 -1 0 1 -1
0 1 -1 1 0 -1 0 1 -1

예제 출력 1

1
2
3
10
12
11

힌트


출처


알고리즘 분류


시간 제한


풀이


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import sys

input = sys.stdin.readline

N = int(input())
paper_list = [list(map(int, input().split())) for _ in range(N)]
result = []


def check_same(x, y, d):
paper = paper_list[x][y]
for i in range(x, x + d):
for j in range(y, y + d):
if paper_list[i][j] != paper:
return False
return True


def solution(x, y, d):
if check_same(x, y, d):
if paper_list[x][y] == 1:
result.append(1)
elif paper_list[x][y] == 0:
result.append(0)
elif paper_list[x][y] == -1:
result.append(-1)
else:
d //= 3
solution(x, y, d)
solution(x + d, y, d)
solution(x + 2 * d, y, d)

solution(x, y + d, d)
solution(x + d, y + d, d)
solution(x + 2 * d, y + d, d)

solution(x, y + 2 * d, d)
solution(x + d, y + 2 * d, d)
solution(x + 2 * d, y + 2 * d, d)


solution(0, 0, N)
print(result.count(-1))
print(result.count(0))
print(result.count(1))

[백준] 1992번 쿼드트리

[백준] 1992번 쿼드트리

출처: [백준] 1992번 쿼드트리


문제

흑백 영상을 압축하여 표현하는 데이터 구조로 쿼드 트리(Quad Tree)라는 방법이 있다. 흰 점을 나타내는 0과 검은 점을 나타내는 1로만 이루어진 영상(2차원 배열)에서 같은 숫자의 점들이 한 곳에 많이 몰려있으면, 쿼드 트리에서는 이를 압축하여 간단히 표현할 수 있다.

주어진 영상이 모두 0으로만 되어 있으면 압축 결과는 “0”이 되고, 모두 1로만 되어 있으면 압축 결과는 “1”이 된다. 만약 0과 1이 섞여 있으면 전체를 한 번에 나타내지를 못하고, 왼쪽 위, 오른쪽 위, 왼쪽 아래, 오른쪽 아래, 이렇게 4개의 영상으로 나누어 압축하게 되며, 이 4개의 영역을 압축한 결과를 차례대로 괄호 안에 묶어서 표현한다

img

위 그림에서 왼쪽의 영상은 오른쪽의 배열과 같이 숫자로 주어지며, 이 영상을 쿼드 트리 구조를 이용하여 압축하면 “(0(0011)(0(0111)01)1)“로 표현된다. N ×N 크기의 영상이 주어질 때, 이 영상을 압축한 결과를 출력하는 프로그램을 작성하시오.


입력

첫째 줄에는 영상의 크기를 나타내는 숫자 N 이 주어진다. N 은 언제나 2의 제곱수로 주어지며, 1 ≤ N ≤ 64의 범위를 가진다. 두 번째 줄부터는 길이 N의 문자열이 N개 들어온다. 각 문자열은 0 또는 1의 숫자로 이루어져 있으며, 영상의 각 점들을 나타낸다.


출력

영상을 압축한 결과를 출력한다.


예제 입력 1

1
2
3
4
5
6
7
8
9
8
11110000
11110000
00011100
00011100
11110000
11110000
11110011
11110011

예제 출력 1

1
((110(0101))(0010)1(0001))

힌트


출처


알고리즘 분류


시간 제한


풀이


소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import sys

input = sys.stdin.readline

N = int(input())

pixel_list = [list(map(int, input().rstrip())) for _ in range(N)]

result = []


def check_same(x, y, d):
pixel = pixel_list[x][y]
for i in range(x, x + d):
for j in range(y, y + d):
if pixel_list[i][j] != pixel:
return False
return True


def solution(x, y, d):
if check_same(x, y, d):
if pixel_list[x][y]:
result.append(1)
else:
result.append(0)
else:
d //= 2
result.append('(')
solution(x, y, d)
solution(x, y + d, d)
solution(x + d, y, d)
solution(x + d, y + d, d)
result.append(')')


solution(0, 0, N)
for x in result:
print(x, end="")

[백준] 2630번 색종이 만들기

[백준] 2630번 색종이 만들기

출처: [백준] 2630번 색종이 만들기


문제

아래 <그림 1>과 같이 여러개의 정사각형칸들로 이루어진 정사각형 모양의 종이가 주어져 있고, 각 정사각형들은 하얀색으로 칠해져 있거나 파란색으로 칠해져 있다. 주어진 종이를 일정한 규칙에 따라 잘라서 다양한 크기를 가진 정사각형 모양의 하얀색 또는 파란색 색종이를 만들려고 한다.

img

전체 종이의 크기가 N×N(N=2k, k는 1 이상 7 이하의 자연수) 이라면 종이를 자르는 규칙은 다음과 같다.

전체 종이가 모두 같은 색으로 칠해져 있지 않으면 가로와 세로로 중간 부분을 잘라서 <그림 2>의 I, II, III, IV와 같이 똑같은 크기의 네 개의 N/2 × N/2색종이로 나눈다. 나누어진 종이 I, II, III, IV 각각에 대해서도 앞에서와 마찬가지로 모두 같은 색으로 칠해져 있지 않으면 같은 방법으로 똑같은 크기의 네 개의 색종이로 나눈다. 이와 같은 과정을 잘라진 종이가 모두 하얀색 또는 모두 파란색으로 칠해져 있거나, 하나의 정사각형 칸이 되어 더 이상 자를 수 없을 때까지 반복한다.

위와 같은 규칙에 따라 잘랐을 때 <그림 3>은 <그림 1>의 종이를 처음 나눈 후의 상태를, <그림 4>는 두 번째 나눈 후의 상태를, <그림 5>는 최종적으로 만들어진 다양한 크기의 9장의 하얀색 색종이와 7장의 파란색 색종이를 보여주고 있다.

img

입력으로 주어진 종이의 한 변의 길이 N과 각 정사각형칸의 색(하얀색 또는 파란색)이 주어질 때 잘라진 하얀색 색종이와 파란색 색종이의 개수를 구하는 프로그램을 작성하시오.


입력

첫째 줄에는 전체 종이의 한 변의 길이 N이 주어져 있다. N은 2, 4, 8, 16, 32, 64, 128 중 하나이다. 색종이의 각 가로줄의 정사각형칸들의 색이 윗줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 하얀색으로 칠해진 칸은 0, 파란색으로 칠해진 칸은 1로 주어지며, 각 숫자 사이에는 빈칸이 하나씩 있다.


출력

첫째 줄에는 잘라진 햐얀색 색종이의 개수를 출력하고, 둘째 줄에는 파란색 색종이의 개수를 출력한다.


예제 입력 1

1
2
3
4
5
6
7
8
9
8
1 1 0 0 0 0 1 1
1 1 0 0 0 0 1 1
0 0 0 0 1 1 0 0
0 0 0 0 1 1 0 0
1 0 0 0 1 1 1 1
0 1 0 0 1 1 1 1
0 0 1 1 1 1 1 1
0 0 1 1 1 1 1 1

예제 출력 1

1
2
9
7

힌트


출처


알고리즘 분류


시간 제한


풀이


소스코드

1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import sys

input = sys.stdin.readline

N = int(input())

paper_list = [list(map(int, input().split())) for _ in range(N)]

result = [] # white(0), blue(1)


def check_same(x, y, d):
color = paper_list[x][y]
for i in range(x, x + d):
for j in range(y, y + d):
if paper_list[i][j] != color:
return False
return True


def solution(x, y, d):
if check_same(x, y, d):
if paper_list[x][y]:
result.append(1)
else:
result.append(0)
else:
d //= 2
solution(x, y, d)
solution(x + d, y, d)
solution(x, y + d, d)
solution(x + d, y + d, d)


solution(0, 0, N)
print(result.count(0))
print(result.count(1))