zoukankan      html  css  js  c++  java
  • [知识点] 2.6 倍增思想

    总目录 > 2 算法基础 > 2.6 倍增思想

    前言

    倍增通常和二分一起介绍,共同点在于——它们都能神奇地将原本复杂度为 n 的过程下降到 log n,对于大型数据而言,这种效率的提高是显而易见的。

    子目录列表

    1、二进制与倍增

    2、例题

    3、应用

    2.6 倍增思想

    1、二进制与倍增

    众所周知,二进制与十进制转换关系:o = 2 ^ a * + 2 ^ b + ... + 2 ^ i,比如 77 = 2 ^ 6 + 2 ^ 3 + 2 ^ 2 + 2 ^ 0,则其二进制表示为 1001101。换言之,任何一个整数都可以由若干个系数为 1,x 为 2 的 2 次方幂的和组成。

    所以尤记得小学时有个比较经典的问题:

    如何用尽可能少的砝码称量出 [1, 30] 之间的所有重量?(天平左侧放物品右侧放砝码)

    根据上述原理,则只需要 1, 2, 4, 8, 16 五个重量级的砝码即可,能够组成 [1, 30] 之间的任意数。

    如果修改成 [1, 60] 呢?多一个 32 即可;

    如果修改成 [1, 21647483647] 呢?则再加上 2 ^ 6, 2 ^ 7, ..., 2 ^ 30,总共也只需要 31 个砝码。

    注意到,我们将这个看似巨大的数字,通过这个思路,很轻松地就得到了 log n 级别的一个结果。而倍增思想,字面意思就是翻倍,其实就是建立在二进制和十进制这个关系上的。

    2、例题

    给出一个长度为 n 的环和一个常数 k,每次可以从第 i 个点跳到第 (i + k) mod (n + 1) 个点,总共跳 m 次。第 i 个点的权值为 a[i],求 m 次跳跃的起点的权值之和 mod 1e9 + 7。

    (原题面没有给出初始位置?)

    强调一下数据范围:m <= 1e18,也就是说我们不可能对于每一次跳跃都记录位置。由于只需要知道 m 次跳跃的权值和,过程其实并不重要,那么就可以采用倍增的方式。

    假设 n = 5, m = 29,将环拆成线性的。下图为跳跃图解:

    选择在终点之前最远的跳跃方式:从第 1 个位置跳到第 9 个位置。

    从第 9 个位置跳到第 13 个位置。

    最后从第 13 个位置跳到第 14 个位置,图略。

    所以从 1 到 14 的整个跳跃过程由 2 ^ 3 + 2 ^ 2 + 2 ^ 0 三步组成。也就是说,对于环上这 n 个位置,预处理出每一个位置向前跳 1, 2, 4, ... 次的位置,则必然能够到达 m。1e18 <= 2 ^ 64,至多倍增跳跃 64 次就够了,而预处理过程同样只需要 O(n log m) 的时间/空间复杂度

    代码略。

    3、应用

    倍增思想最常见的应用:快速幂,LCA 和 RMQ 问题等等。

    快速幂请参见:6.2 快速幂

    倍增 LCA 请参见:<施工中>

    RMQ 问题请参见:<施工中>

  • 相关阅读:
    PHP的文件下载
    ajax异步请求分页显示
    Linux的启动过程
    搭建nginx反向代理用做内网域名转发
    intellij idea 修改背景保护色&&修改字体&&快捷键大全
    IDEA入门级使用教程-
    http://blog.csdn.net/baidu_31657889/article/details/52315902
    JVM——Java虚拟机架构
    MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题
    windows上 nginx 配置代理服务,配置多域名,以及最简单实现跨域配置
  • 原文地址:https://www.cnblogs.com/jinkun113/p/12876129.html
Copyright © 2011-2022 走看看