대괄호 문자가 정확히 2k개 등장한다고 하자. 그 위치를 고르는 방법은 (2kN)가지이고, 나머지 위치에는 각각 대괄호가 아닌 문자 6개 중 하나를 놓을 수 있다. 선택된 2k개의 위치에 올바른 괄호 문자열을 놓는 방법의 수는 카탈란 수
Cat(k)=k+11(k2k)
이다. 따라서 컴파일되는 길이 N의 문자열 수를 AN이라 하면
AN=k=0∑⌊N/2⌋(2kN)Cat(k)6N−2k
이다. 한 테스트 케이스만 처리한다면 이 식을 직접 계산하여 O(N)에 해결할 수 있다.
전체 테스트 케이스를 빠르게 처리하기 위해 모든 AN을 선형 시간에 전처리한다. [를 높이를 1 올리는 걸음, ]를 높이를 1 내리는 걸음, 나머지 여섯 문자를 높이를 유지하는 서로 다른 6개의 걸음으로 보면, 컴파일되는 문자열은 높이가 음수가 되지 않고 마지막에 0으로 돌아오는 가중 Motzkin 경로와 같다.
생성함수를
F(x)=n≥0∑Anxn
이라 하자. 첫 걸음을 기준으로 분해하면
F(x)=1+6xF(x)+x2F(x)2
이고, 따라서
F(x)=2x21−6x−1−12x+32x2
이다. 이를 미분하고 정리하면
x(1−12x+32x2)F′(x)+(2−18x+32x2)F(x)−2=0
을 얻는다. xn의 계수를 비교하면 n≥2에 대해
(n+2)An=6(2n+1)An−1−32(n−1)An−2
이다.
실제로 필요한 값은 확률
Rn=8nAn
이다. 위 점화식을 8n으로 나누면
(n+2)Rn=43(2n+1)Rn−1−2n−1Rn−2
이고, 초깃값은 R0=1, R1=43이다.
법 998244353에서 2, 4, 그리고 2≤n+2≤100002는 모두 역원을 가진다. 따라서 위 점화식을 그대로 모듈러 연산으로 계산할 수 있다. 입력에서 가장 큰 값을 M이라 하면 R0,R1,…,RM을 한 번 전처리하고 각 질의에 RN을 출력한다.
시간 복잡도는 O(M+T)이고, 공간 복잡도는 O(M+T)이다.
또한 원래 확률의 분모는 기약분수로 줄이기 전 8N이므로, 기약분수의 분모 역시 998244353과 서로소이다.