알고리즘 블로그
article thumbnail

지문이 짧길래 저번에 카페에서 떠들다가 핸드폰 메모장을 이용해서 대충 풀이를 내봤는데 흥미로웠다.

어제 메모장 정리하다 메모를 발견해서 구현해보았다.

 

일단 문제 자체가 너무 점화식으로 잘 표현될 수 있을 거라는 느낌을 풍긴다.

이 문제의 어려움은 $n+1$개의 직사각형 중 $n$개는 정확히 계단 모서리에 하나씩 걸치지만 딱 한 개의 직사각형은 중앙 어디에든 위치할 수 있다는 점에 있다.

 

따라서 중앙 어디에든 위치할 수 있는 직사각형의 위치를 고정시킨다면 문제가 수월해질 것이다.

 

고정했다고 생각하고 문제를 바라보면, 직사각형의 두 변을 연장해서 가능한 답의 꼴들을 찾아볼 수 있다.
무조건 두 변 중에 한 변의 연장선은 어떤 조각도 가로지르지 않는다는 관찰이 핵심적이다.

 

이를 이용하여 약간의 포함배제를 적용하면 문제를 해결할 수 있다.

 

 

#include <bits/stdc++.h>
#define rep(i,a,b) for (ll i = (a); i <= (b); ++i)
using namespace std; using ll = long long;

const ll N = 103;
ll n, M;
ll C[N], D[N];

signed main() {
    cin.tie(0)->sync_with_stdio(0);
    cin >> n >> M;
    D[0] = D[1] = 1;
    rep(i,2,n) {
        rep(j,0,i-1) {
            D[i] += D[j]*D[i-j-1]%M;
            D[i] %= M;
        }
    }
    rep(i,1,n) {
        rep(x,1,i) rep(y,1,i-x) {
            // 1<=x,y && x+y<=i
            C[i] += D[x]*D[i-x]%M;
            C[i] += D[y]*D[i-y]%M;
            C[i] -= D[x]*D[y]%M*D[i-x-y]%M;
            C[i] %= M;
        }
        if (C[i]<0) C[i] += M;
    }

    rep(i,1,n) {
        ll ans=0;
        rep(x,0,i) rep(y,0,i-x) {
            // 0<=x,y && x+y<=i
            ans += D[x+y]*C[i-x-y]%M;
            ans %= M;
        }
        if (ans<0) ans += M;
        cout << ans << ' ';
    }
}

'PS 문제들' 카테고리의 다른 글

[BOJ 29203] 테마파크  (0) 2024.10.02
5월 알고리즘  (4) 2024.06.16
[2022 Yokohama Regional] Make a Loop (BOJ 27421)  (3) 2023.11.08
[NYPC 2022 Round 2-A] 로봇 청소기 ★  (0) 2023.10.24
[APIO 2021] 밀림 점프 (BOJ 21852) ★  (0) 2023.10.23
profile

알고리즘 블로그

@도훈.

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...