做到了 ABC448E,感觉很精妙。

题目中有个部分是模意义下等比数列求和。那么来讲讲它的几种做法。

公式

直接套公式。

$$ \sum_{i=0}^n a^i = \frac{a^{n+1}-1}{a-1} $$

然后用逆元。不讲。

如果等比数列不是从 1 开始的,提取首项为公因数即可。下面所有讨论都默认 1 为首项。

更好的方法

公式法需要逆元,在逆元不存在时就寄了。而恰好,448E 的模数不是质数。

我们有几种方法来处理这个情况

下文定义

$$ f(l, a) = \sum_{i = 0}^{l-1} a^i $$

分治求和

洛谷已经有篇文章讲过这种手法了。我在场上推出来也受到了它的启发。

大概来说,我们将序列平均分为两部分。

$$ f(l, a) = \begin{cases} (1+a^{l/2})x, \; l \text{ is even}\\ x+a^{(l-1)/2}(ax+1), \; l \text{ is odd} \end{cases} $$

其中 $x := f(\lfloor \frac{l}{2} \rfloor, a)$。

这样,做分治再套快速幂就可以以 2log 复杂度解决。不过这样不够优秀。

两种优化的分治

维护幂信息

注意到每层递归重算快速幂非常不优。我们在计算 $f(l, a)$ 时顺便维护 $a^l$,在计算完 $x$ 之后将 $a^{\lfloor \frac{l}{2} \rfloor}$ 平方就得到 $a^l$。

复杂度单 log。

奇偶分拆

从中部分开不是非常优秀。考虑类似 FFT 的方法,把奇数和偶数位置拆开算。

$$ f(l, a) = \begin{cases} (1+a)x, \; l \text{ is even}\\ a(1+a)x+1, \; l \text{ is odd} \end{cases} $$

其中 $x := f(\lfloor \frac{l}{2} \rfloor, a^2)$。

同样复杂度 1log。

矩阵快速幂

注意到等比数列求和是一种常系数线性递推:

$$ f(l, a) = \begin{cases} 1, \; l=1\\ af(l-1,a)+1, \; \text{otherwise} \end{cases} $$

于是自然可以矩阵快速幂维护。用 2 阶方阵作为转移矩阵。

$$ T := \begin{bmatrix} a & 1 \\ 0 & 1 \end{bmatrix} $$

$$ T \begin{bmatrix} x \\ 1 \end{bmatrix} = \begin{bmatrix} ax+1 \\ 1 \end{bmatrix} $$

于是:

$$ T^{l-1} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} f(l, a) \\ 1 \end{bmatrix} $$

模数扩张

非常精妙的一种做法。

回想 448E 里我们用的另一个技巧。为了维护一个数除以另一个数下取整的值模 10007,我们推导出了这个式子:

$$ \lfloor \frac{a}{b} \rfloor \bmod p = \lfloor \frac{a \bmod pb}{b} \rfloor \bmod p $$

回到最初的公式:

$$ f(l, a) = \frac{a^l-1}{a-1} $$

那么:

$$ \frac{a^l-1}{a-1} \bmod p = \frac{(a^l-1) \bmod p(a-1)}{a-1} \bmod p $$

只需要算一次快速幂即可。

注意特判 $a = 1$ 的情况(和普通公式法一样)。