https://www.acmicpc.net/problem/13976
13976번: 타일 채우기 2
첫째 줄에 N(1 ≤ N ≤ 1,000,000,000,000,000,000)이 주어진다.
www.acmicpc.net
타일 채우기라고 부르는 유형은 풀이법이 어느정도는 정해져 있습니다.
보통 점화식을 구해야하는데, 그 과정에서, 다음 과정을 거칩니다.
- 작은 $N$ 값에 대해 답을 구해봅니다
- 적당히 큰 값의 $X$ 에 대해서, 가로로 $X$ 만큼의 크기(이 문제에서는 $3\;by\;X$ )를 얻었다고 칩니다
- 그 다음 $X+1$ , $X+2$ , 로 확장해가면서 점화식을 추론합니다
이 글에서도 위와 같은 과정을 거칠 것입니다.
우선 $N=2$ 일 때, 답은 3입니다.
다음과 같은 경우의 수가 있습니다.
$N=4$ 일 때, 답은 11입니다.
다음과 같은 경우의 수가 있습니다.
답을 11이라 했는데 9가지만 제시했죠? 일단 이 9가지는 $N=2$ 일 때의 경우의 수를 활용해서 만든 것입니다.
그리고 남은 2가지는 완전히 새롭게 생긴 것입니다.
이렇게 해서 $N=4$ 일 때의 11가지 경우의 수가 완성 됐습니다.
$N=6,\;8,\;10,\;\cdots$ 의 경우도 직접 구할 수는 있습니다.
하지만, 수열을 이렇게 정의해보겠습니다.
$\left \{ a_{n}\right \}$ : $3\times n$ 크기의 직사각형을 만드는 방법의 수
그러면, 적당히 큰 $x$ 에 대해, $a_{x},\;a_{x-2}\;\cdots\;a_{2}$ 을 통해 $a_{x+2}$ 를 만들어 보겠습니다.
또한 그림 2.2. 와 같은 형태가 모든 $N\geq2$ 에 대해 존재한다고 가정하겠습니다.
그 형태를 odd 라고 부르겠습니다.
이제 $a_{x+2}$ 를 만드는 방법은,
$a_{2}$ 의 상태에서, 가로 길이가 $x$ 인 odd 2가지
$a_{4}$ 의 상태에서, 가로 길이가 $x-2$ 인 odd 2가지
$\vdots$
$a_{x-2}$ 의 상태에서, 가로 길이가 $4$ 인 odd 2가지
$a_{x}$ 의 상태에서 남은 $3\times 2$ 공간을 채울 방법 $a_{2}=3$ 가지
$x+2$ 의 길이를 갖는 odd가 2가지
따라서, 다음 식이 유도됩니다.
$a_{x+2}=3\times a_{x}+2\times \left ( a_{x-2}+a_{x-4}+\cdots+a_{2} \right )+2$
여기까지 했다면 마지막 스텝이 남았습니다.
점화식의 크기가 $x$ 에 비례하고, $N$ 의 상한이 아주 큰 값이어서 식을 변형해야 합니다.
위 식에 따라 다음을 얻습니다.
$a_{x}=3\times a_{x-2}+2\times \left ( a_{x-4}+a_{x-6}+\cdots+a_{2} \right )+2$
이제 식끼리 빼면, 공통 부분이 삭제되면서 다음을 얻습니다.
$a_{x+2}=4\times a_{x}-a_{x-2}$
이를 행렬로 표현하면 다음과 같습니다.
$\begin{bmatrix} a_{x+2} \\ a_{x} \end{bmatrix}=\begin{bmatrix} 4 & -1 \\ 1 & 0 \end{bmatrix} \begin{bmatrix} a_{x} \\ a_{x-2} \end{bmatrix}$
$x$ 가 충분히 큰 값이었음에 주의하며, 최종적으로 다음 식을 얻습니다.
$\begin{bmatrix} a_{N} \\ a_{N-2} \end{bmatrix}=\begin{bmatrix} 4 & -1 \\ 1 & 0 \end{bmatrix}^{\frac{N}{2}} \begin{bmatrix} a_{2} \\ a_{0} \end{bmatrix}$
그런데 $a_{0}$ 에는 어떤 값이 들어가야 할까요?
점화식에 $x=2$ 를 대입하면, $a_{4}=4\times a_{2}-a_{0}$ 이므로, $a_{0}=1$ 이라 말할 수 있습니다.
애초에 문제에서 주어지는 $N>0$ 이므로 $a_{0}$ 값은 아귀가 맞기만 하면 충분합니다.
그래서, 우리가 계산해야 할 것은 다음과 같습니다.
$\begin{bmatrix} a_{N} \\ a_{N-2} \end{bmatrix}=\begin{bmatrix} 4 & -1 \\ 1 & 0 \end{bmatrix}^{\frac{N}{2}} \begin{bmatrix} 3 \\ 1 \end{bmatrix}$
한편, 우리가 구한 것은 $N$ 이 짝수인 경우이지만, $N$ 이 홀수인 경우의 답은 쉽게 알 수 있습니다.
사용할 수 있는 블록의 넓이는 모두 짝수인데, $N$ 이 홀수이면 $3\times N$ 도 홀수이므로 전부 채울 수 없습니다.
따라서 경우의 수는 0입니다.
예외처리와 음수 모듈러에 주의하며 구현한 최종 코드는 다음과 같습니다.
#include <stdio.h>
#define mod 1000000007
typedef struct {
long long array[2][2];
} Matrix;
Matrix matrix_multiply_modular (Matrix A, Matrix B);
Matrix matrix_power_modular (Matrix Base, long long power);
int main() {
long long N;
scanf("%lld", &N);
if (N % 2) {
printf("0");
}
else {
Matrix Base = { {{0,1},{-1,4}} };
Matrix Answer = { {{1,0},{3,0}} };
Base = matrix_power_modular (Base, N/2);
Answer = matrix_multiply_modular (Base, Answer);
printf("%lld", Answer.array[0][0]);
}
return 0;
}
Matrix matrix_multiply_modular (Matrix A, Matrix B) {
Matrix result = { {{0}} };
for (int i = 0; i < 2; i++) {
for (int k = 0; k < 2; k++) {
for (int j = 0; j < 2; j++) {
long long temp = (A.array[i][k] * B.array[k][j] + mod) % mod;
result.array[i][j] = (result.array[i][j] + temp) % mod;
}
}
}
return result;
}
Matrix matrix_power_modular (Matrix Base, long long power) {
Matrix result = { {{1,0},{0,1}} };
while(power) {
if (power % 2) {
result = matrix_multiply_modular (result, Base);
}
Base = matrix_multiply_modular (Base, Base);
power /= 2;
}
return result;
}
(1116KB, 0ms, 제출번호 31122126)
이 글을 올리는 시점에선, 문제에 대해 아직 잘 모르는 게 좀 있습니다.
왜 odd는 항상 두 개만 존재할 수 있을까요?
$a_{0}=1$ 인 것은 $\binom{0}{0}=1$ 인 것처럼 뭔가 의미부여가 가능할 수는 있지만
odd에 관한 것은 잘 모르겠습니다.
'분할 정복을 이용한 거듭제곱 > 행렬 거듭제곱' 카테고리의 다른 글
백준 3827번: 일차원 세포 자동자 (0) | 2021.07.31 |
---|---|
백준 15999번: 뒤집기 (0) | 2021.07.30 |
백준 1529번: 동민 수열 (0) | 2021.07.17 |
백준 19587번: 객실 배치 (0) | 2021.07.17 |
백준 12878번: Blocks (0) | 2021.07.17 |