넘치게 채우기

[BOJ] 15569 - 블록 1 본문

PS/BOJ

[BOJ] 15569 - 블록 1

riveroverflow 2025. 9. 4. 15:13
728x90
반응형

https://www.acmicpc.net/problem/15569

BOJ - 블록 1

문제 유형: 다이나믹 프로그래밍

문제 난이도: Gold III

시간 제한: 1초

메모리 제한: 256MB

 

문제

여러 가지 블록들을 이용하여 직사각형 모양을 만들려고 한다. 우리에게는 1 × N 블록, 2 × N 블록, ..., N × N 블록이 무한하게 있다. 이 블록들을 사용하여 N × M 모양을 만들고 싶다. 만들 수 있는 총 방법의 수를 1999로 나눈 나머지를 구하여라.

 

입력

첫 번째 줄에 N과 M이 입력된다. (1 ≤ N ≤ 10^2, 1 ≤ M ≤ 10^4)

 

출력

총 가능한 경우의 수를 1999로 나눈 나머지를 출력한다.

 

풀이

dp[i][j] = i x j의 타일을 구성하는 경우의 수로 한다.

 

보통의 경우는 a x n짜리(a < n) 타일을 세로로 나열하여 구성하는 식을 생각하면 된다.그러나, n x n이상부터는, 회전을 고려하여야 한다. 여기부터는 회전이 가능하기 때문이다.

 

base case로, dp[0][n] = dp[1][n] = dp[n][1] = 1가지이다.

먼저, i <= n부터 고려하자.

dp[i][n] = sum of (dp[i-j][n]) for j in 1 ... i이다.

그리고, 대칭이므로 dp[i][n] = dp[n][i]이다.

 

그리고, n x n은 가로로 눕힌 경우의 수들도 고려해야 한다.

dp[n][n]에 두 배를 곱하고, n x n자체는 중복이므로 1을 뺀다.

이 연산을 취하기 전에, 변수에 dp[n][n]을 담아둔다.

 

이제, i > n일때는,

j < n인경우는 이전처럼 이어붙이면 되지만, j = n인경우, bnr을 곱해서 회전 가능한 n x n블록을 고려한다.

 

답은 dp[n][m]이다.

 

코드

Go

package main

import (
	"bufio"
	"fmt"
	"os"
)

const MOD int = 1999

var reader *bufio.Reader
var writer *bufio.Writer

var n, m int

func main() {
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	fmt.Fscan(reader, &n, &m)

	dp := make([][]int, n+1)
	mx := max(n, m)
	for i := 0; i <= n; i++ {
		dp[i] = make([]int, mx+1)
	}

	dp[0][n] = 1
	dp[1][n] = 1
	dp[n][1] = 1
	for i := 2; i <= n; i++ {
		for j := 1; j <= i; j++ {
			dp[i][n] += dp[i-j][n]
		}
		dp[i][n] %= MOD
		dp[n][i] = dp[i][n]
	}

	bnr := dp[n][n]
	dp[n][n] = ((dp[n][n] * 2) - 1) % MOD
	for i := n + 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if j == n {
				dp[n][i] += dp[n][i-j] * bnr
			} else {
				dp[n][i] += dp[n][i-j]
			}
		}
		dp[n][i] %= MOD
	}

	fmt.Fprintln(writer, dp[n][m])
}
728x90
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 20553 - 다오와 디지니의 데이트  (0) 2025.09.07
[BOJ] 29333 - One Walk  (0) 2025.09.06
[BOJ] 25306 - 연속 XOR  (0) 2025.09.03
[BOJ] 31791 - 바이러스 공격  (0) 2025.09.02
[BOJ] 특별한 서빙  (0) 2025.09.01