昨天写了一道题,大概是这样的,给出一个三阶递推数列,求第(n)项的值。然后本蒟蒻大力推通项,搞出了(frac{(4n-13)*3^{n+2}+36+15*(-1)^n}{32})这个东西。
题目有(T)组询问((1leq Tleq 5*10^7)),每次询问的(n)在long long范围内,且要求对(1e9+7)取模。当时没想那么多,直接一发快速幂提交了,然后大数据的点全T掉了。。。
回过头去发现对于单个(n)的求值要求O(1)完成。思考一番,由于(p=1e9+7)是质数,所以由费马小定理得(a^{p-1}equiv 1(mod p)),然后求快速幂时传过去的指数可以变成(n) (mod) ((p-1)),
单次求解复杂度变成了原来的一半,还是会T。之后又考虑了各种卡常,没有用。然后就滚去参考(抄袭)题解了。
发现唯一的不同就是高次幂的求法。(p)是在(2^{32})以内,如果我们以(2^{16}=65536)作为一个基准,那么所有的指数都可以表示为(n/65536*65536+n:mod: 65536)这种形式(这里/号是整除)。
这有什么用呢?接下来指数(leq 65536)的数原样不变,指数(>65536)的写成((3^{65536})^{n/65536}*3^{n: mod: 65536})。开两个数组,一个表示(3^i),一个表示((3^{65536})^i)。
由于之前的等价处理,所以n变成了(1e9+7)以内的数,所以(frac{n}{65536}leq 65536),不会炸空间;而预处理两个数组之后单次求解的时间复杂度是O(1),写题解的神仙把它取名叫光速幂。
注意:上文对n的变换只用于快速幂步骤,前面的(4n-13)还是要用原来的(n)去算的。
题目链接:https://www.luogu.com.cn/problem/P5517
代码就不贴了,相信大家都能自己写出来。