【黑科技学习】光速幂

昨天写了一道题,大概是这样的,给出一个三阶递推数列,求第\(n\)项的值。然后本蒟蒻大力推通项,搞出了\(\frac{(4n-13)*3^{n+2}+36+15*(-1)^n}{32}\)这个东西。

题目有\(T\)组询问(\(1\leq T\leq 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

代码就不贴了,相信大家都能自己写出来。

posted @ 2020-10-20 11:17  文艺平衡树  阅读(754)  评论(0编辑  收藏  举报