jbs30_jsh 님의 풀이를 보고 영감을 받아 작성한 글입니다.
우선 각각의 n에 대해서, 대칭 축 기준 왼쪽에 k쌍의 괄호가 존재하는 경우의 수를 h(n,k)라고 정의합시다. 그러면 아래와 같은 식이 성립하게 됩니다.
h(n,k)=h(n−1,k−1)+h(n−1,k)
∴h(1,0)=1
문제를 보면 색깔 K개가 주어집니다. 만약에 대칭 축 기준으로 왼쪽에 k쌍의 괄호가 있다면 색칠하는 경우의 수는 Kn−k가 됩니다.
이 때, Kn−kh(n,k) 를 모두 더하면 우리가 원하는 답이 도출됩니다. 이것을 s(n)이라 정의하고, 또한 어떤 n에 대해 대칭 축 기준으로 한 쪽에만 존재할 수 있는 최대 괄호 쌍 개수를 L(n)이라 정의합시다.
이 때,
s(n)=i=0∑L(n)Kn−ih(2n+1,i)
이며, 또한 L(2n)=L(2n+1)=n 이라는 사실을 알 수 있습니다..
s(2n+1)/K=i=0∑nK2n−ih(2n+1,i)
s(2n)=i=0∑nK2n−ih(2n,i)
s(2n+1)/K−s(2n)
=i=0∑nK2n−ih(2n,i−1)
=i=0∑nK2n−i−1h(2n,i)
=s(2n)/K−Kn−1h(2n,n)
∴s(2n+1)=s(2n)(K+1)−Knh(2n,n)
이 때, h(2n,n)에 대해서도 살펴봅시다.
s(2n)=i=0∑nK2n−ih(2n,i)
ks(2n−1)=i=0∑n−1K2n−ih(2n−1,i)
s(2n)−ks(2n−1)=Knh(2n,n)+i=0∑n−1K2n−ih(2n−1,i−1)
=Knh(2n,n)+i=0∑n−2K2n−i−1h(2n−1,i)=s(2n−1)+Knh(2n,n)−Knh(2n−1,n−1)
이 때 h(2n,n)의 의미는, 중심축을 기준으로 좌우 각각 n개의 괄호들이 위치함을 알 수 있습니다. 한 쪽에 괄호를 배치하면 다른 쪽 괄호의 배치는 저절로 정해지기에, 괄호를 올바르게 배열하는 경우의 수는 Cn번째 카탈란 수 입니다.
카탈란 수란
C0=1andCn=i=0∑n−1CiCn−i−1forn≥1
라는 점화식 또는
Cn=n!(n+1)!(2n)!
라는 조합으로 나타내어 지는 수열입니다.
따라서, h(2n,n)=h(2n−1,n−1)=Cn임을 알 수 있습니다.
s(2n)=s(2n−1)(K+1)
s(2n+1)=s(2n)(K+1)−KnCn=s(2n−1)(K+1)2−KnCn
(K+1)2ns(2n+1)=(K+1)2n−2s(2n−1)−((K+1)2K)nCn
bn=(K+1)2ns(2n+1)
bn=bn−1−((K+1)2K)nCn
bn−1−bn=((K+1)2K)nCn
K−bn=i=1∑n((K+1)2K)iCi
bn=K−i=1∑n((K+1)2K)iCi
∴s(2n+1)=K(K+1)2n−i=1∑nKi(K+1)2n−2iCi
시간복잡도는 O(nlogn)에 동작합니다.
코드를 처음에는 python으로 구현하였으나, 이 쓰레기같은 언어가 시간을 버티지 못하여 C++로 재구현하였습니다.
#include <iostream>
#define MOD 1000000007
using namespace std;
long long power(long long x, long long y) {
long long r = 1;
while (y) {
if (y & 1) r = (r * x) % MOD;
y >>= 1;
x = x * x % MOD;
}
return r;
}
int main() {
long long result = 0, mate = 1, n, k, bracket, temp;
cin >> n >> k;
bracket = n / 2 - (n & 1 ? 0 : 1);
result = k * power(k + 1, bracket * 2) % MOD;
for (long long i = 1; i < bracket + 1; i++) {
temp = power(k + 1, bracket * 2 - i * 2) * power(k, i) % MOD * mate % MOD;
mate = mate * (i * 4 + 2) % MOD * power(i + 2, MOD - 2) % MOD;
result -= temp;
result %= MOD;
}
if (n % 2 == 0) {
result *= k + 1;
result %= MOD;
}
cout << (result + MOD) % MOD;
}