위 그림에 제시된 것과 같은 모양의 두 종류의 타일이 있다.
각 타일은 90도마다 회전이 가능한데, 이때 가로 n (n은 자연수), 세로 3으로 타일링을 할 수 있는 경우의 수를 구하는 문제다.
핵심 풀이법은 점화식을 구하는 일이다.
그런데 이 문제는 점화식을 구하는 것부터 쉽지 않다.
그나마 다행인 점은, n > 3인 경우, 3으로 나눈 나머지가 1, 2, 0일 때 새롭게 추가되는 유형의 타일링이 2, 2, 4개로 반복된다는 점이다. (힌트 참고)
그렇지만 점화식을 확인하기 위해, n = 6까지의 타일링을 할 수 있는 경우의 수는 직접 구해야 했다.
경우의 수를  이라 할 때  이 나오게 됨을 확인하였는데, 여기서 점화식을 추출해야 한다. n = 4, 5, 6일 때 각각 다음과 같이 추출된다.
이를 일반화하면  이 되는데, S(n-4) 항부터는 계수가 2, 2, 4로 반복되는 점을 이용하여 을 계산 가능하며,
 이 된다.
이를 정리하여 행렬로 나타내면 다음과 같다.
=
import numpy as np
def matrix_product(arr, L):
    l = len(arr)
    result = [0] * l
    for i in range(l):
        for j in range(l):
            result[i] += arr[i][j] * L[-j-1]
            result[i] %= 1000000007
    return result%1000000007
def solution(n):
    S = [1, 3, 10, 23, 62, 170]
    if n < 7:
        return S[n-1]
    
    arr = [[1, 2, 6, 1, 0, -1]]
    for i in range(5):
        L = [0] * 6
        L[i] = 1
        arr.append(L)
        
    mtx = [row[:] for row in arr]
    r_matrix = [[0] * 6 for _ in range(6)]
    for i in range(6):
        r_matrix[i][i] = 1
        
    count = n - 3
    while count > 0:
        if count % 2:
            r_matrix = np.dot(r_matrix, mtx)
        mtx = np.dot(mtx, mtx)
        count //= 2
    return matrix_product(r_matrix, S)[3]

numpy를 쓸 경우 dot이든 matmul을 쓰든 런타임 에러가 발생한다.
그런데 numpy를 쓰지 않고 dot product 함수를 직접 정의할 때도 에러가 발생하는데, 그 이유로는 직접 만든 함수 안에서 1,000,000,007로 나누는 값을 return해서 런타임 에러가 난다고 생각했다.
따라서 1,000,000,007을 mod라는 변수에 부여하였으며, numpy를 import하지 않고 내적함수를 직접 정의하여 아래와 같은 코드를 구현하였다.
mod = 1000000007
def dot_product(arr1, arr2):
    l = len(arr1)
    new_arr = [[0] * l for _ in range(l)]
    for i in range(l):
        for j in range(l):
            for k in range(l):
                new_arr[i][j] += arr1[i][k] * arr2[k][j]
            new_arr[i][j] %= mod
    return new_arr
def matrix_product(arr, L):
    l = len(arr)
    result = [0] * l
    for i in range(l):
        for j in range(l):
            result[i] += arr[i][j] * L[-j-1]
            result[i] %= mod
    return result
def solution(n):
    S = [1, 3, 10, 23, 62, 170]
    if n < 7:
        return S[n-1]
    
    arr = [[1, 2, 6, 1, 0, -1]]
    for i in range(5):
        L = [0] * 6
        L[i] = 1
        arr.append(L)
        
    mtx = [row[:] for row in arr]
    r_matrix = [[0] * 6 for _ in range(6)]
    for i in range(6):
        r_matrix[i][i] = 1
        
    count = n - 3
    while count > 0:
        if count % 2:
            r_matrix = dot_product(r_matrix, mtx)
        mtx = dot_product(mtx, mtx)
        count //= 2
    return matrix_product(r_matrix, S)[3]

다른 참고 코드를 볼 수 있었던 것이 운이 좋았다.
답을 참조하고 풀긴 했지만 답을 이해하는 과정도 쉽지 않았던 것 같다.
점화식을 구하면 되는 문제니 쉽게 풀 수 있을 것이라 생각했지만 알고 보니 노가다성이 좀 있는 문제였다는 건 반전.

