문제 링크
- http://icpc.me/19499
사용 알고리즘
- FFT
- Kitamasa
- Fenwick Tree
시간복잡도
- $O(K \log K \log M)$
풀이
정확히 $T$번 연산해서 $N$이 되는 경우의 수를 $g(T, N)$라고 정의합시다. $g(T, N)$은 아래와 같이 표현할 수 있습니다.
\[g(T, N) = \begin{cases} 1 \text{, if } T = 0 \\ g(T-1, Nk) \text{, if } k \vert (N+1) \\ g(T-1, N+1) + g(T-1, Nk) \text{, otherwise} \end{cases}\]입력으로 주어진 $k, m, mod$에 대해 $g(k, m) \mod mod$가 문제의 정답이 됩니다.
여러 $k$에 대해 로컬에서 작은 항을 계산해본 뒤 berlekamp-massey를 돌려보면 선형 점화식을 얻을 수 있습니다. $D(m)$을 문제의 정답이라고 정의하면, 점화식은 아래와 같이 나옵니다.
\[D(m) = \begin{cases}2^m \text{, if } m < k-1 \\ 2^m-1 \text{, if } m = k-1 \\ \displaystyle \sum_{i=1}^{k} D(m-i) \text{, otherwise}\end{cases}\]1 |
|
$k \leq 10^4, m \leq 10^{18}$이므로 Kitamasa와 FFT를 사용하면 $O(k \log k \log m)$에 점화식을 계산할 수 있습니다.
하지만, FFT를 사용한 다항식 나눗셈은 느린 $O(k \log k)$에 속하기 때문에 2초라는 빡빡한 시간 제한을 통과하기 어렵습니다. 최적화를 해야 합니다.
Divisor를 보면, 항상 $C_k(x) = x^k - x^{k-1} - x^{k-2} - x^{k-3} - \cdots - 1$ 꼴이라는 것을 알 수 있습니다. 어떤 다항식을 $C_k(x)$로 나눈 나머지를 구하는 과정을 손으로 직접 계산해보면, 어떤 수 $c$를 적당한 구간 $[i-k, i-1]$에 더하는 연산을 여러 번 수행한다는 것을 알 수 있습니다. 우리는 이런 연산을 Fenwick Tree를 사용해 매우 빠르게 수행할 수 있습니다. 그러므로 다항식 나눗셈을 빠른 $O(k \log k)$에 할 수 있고, AC를 받을 수 있습니다.
전체 코드
1 |
|