zoukankan      html  css  js  c++  java
  • 【黑科技学习】光速幂

    昨天写了一道题,大概是这样的,给出一个三阶递推数列,求第(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

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

  • 相关阅读:
    jQuery对象和DOM对象的互转
    ASP.NET MVC单元测试Controller时添加上下文的方式
    基于Mongodb进行分布式数据存储【转】
    .NET平台上的编译器不完全列表
    实现自己的O/R Mapping组件高效缓存的思考
    .NET的动态语言
    C++类成员和数据成员初始化总结
    ACE Singleton
    Wiresshark
    C++
  • 原文地址:https://www.cnblogs.com/landmine-sweeper/p/13845445.html
Copyright © 2011-2022 走看看