过程比较繁琐,知识比较综合。
题意:在 $L + 1$ 行 $n$ 列的图形上从 $(0, x)$ 随机游走,要求只能向下走,从 $v_1$ 列走到 $v_2$ 列的方案数为 $W_{v_1, v_2}$(与行无关),只能在 $y$ 列停止。给定 $k$,求所有 $t\in[0, k - 1]$,求停留的行的编号满足 $\bmod k = t$ 的所有方案和,答案对 $p$ 取模。满足 $k\leq 2 ^ {16}$,$L\leq 10 ^ 8$,$10 ^ 8 < p < 2 ^ {30}$,$n\leq 3$,$k|p - 1$,$p$ 为质数。
仔细观察发现如果我们确定步数 $k$,行和列的答案是无关的,只需要最后乘起来即可。对于行来说,我们假设多给一步,强制走到 $L + 1$ 的位置,于是插板法容易得到方案数为 $\binom Lk$。对于列来说,这就是一个显然的矩阵乘法,为 $W ^ k[x][y]$。
于是可以得到:
然后看到 $[i\bmod k = t]$,果断单位根反演,于是一波变换:
最后一步我们在 单位根反演 的 T2 中已经见过矩阵合并二项式定理了,这里不再赘述。注意这里单位根需要我们先求出原根计算。
假设后面只关于 $j$ 的一坨记作 $f(j)$,其为 $\sum_{j = 0} ^ {k - 1} \omega_k ^ {-tj} (\omega_k ^ j W + I) ^ L[x][y]$。单个 $f(j)$ 容易在 $\log L$ 的时间完成。
于是我们得到:
看样子这是一个卷积,但是指数上有乘积,不好拆开。
考虑如下两个变换:
两个式子展开一下即可证明。我们惊喜的发现,这个恰好把 $xy$ 化为了 $(x + y)$,这样看样子就可以卷积了!
套用第一个式子:
但是除以 2 不好处理,因为我们可能没法开根。
考虑套用第二个式子:
显然这是一个差卷积,直接做即可,时间复杂度 $O(k\log k)$,可以通过。
另外,这后半部分拆开指数上的乘积其实就是一个叫 BlueStein 的算法。容易发现这个算法其实解决了任意长度的 FFT,因为 FFT 和这个算法都是计算 $n$ 个单位根位置的点值的,只不过 FFT 的 $n$ 是 2 的次幂。更详细的信息看 这篇 Blog。
1 | int main() |