简单提取一下核心:
-------------------------------------------------------------------------------------------------------------------
任意一个整数可以表示成若干个 2的次幂项之和 (通俗来讲就是二进制那种表示法)
-------------------------------------------------------------------------------------------------------------------
“倍增”与“二进制划分” 的思想 是 互相结合 的
-------------------------------------------------------------------------------------------------------------------
最典型的是:
1.RMQ算法(ST算法)
2.树上倍增 (例如 LCA在树上倍增的应用)
一.
下面就以 RMQ 算法 为例,来解释一下什么是倍增的二进制划分?
------------------------------------------------------------------------------------------------------
好像步长会与 2^j 有关 (是指数级别的)
所以涉及倍增的,时间复杂度 都是(对数级别)
------------------------------------------------------------------------------------------------------
max( ) 中 前面的数组 和 后面的数组 的 第二维
表示的 是 步长是 2^(j-1) 次方
但是我们只存 ( j -1 )
二.
下面以 LCA算法 为例,解释一下倍增的二进制划分。
三.
下面以 快速幂 为例, 解释一下倍增的二进制划分
对于快速幂来说,
我们求的是 a^k
我们要把k划分成 log(k)个以2为底的 二进制数
这些数相加==k
然后 a^k 就可以用这些表示:
代码形式为
每次遇到状态里面有1的时候就要 将结果* a
而a也是不断变化的,不断的指数级别变化
从 a 到 a*a 到 a*a*a
四.
什么情况下可以用倍增?
以矩阵乘法举例,一定要具有结合律才可以使用倍增算法。
然后用结合律就是
结合律意味着 可以任意先算哪个,然后再算哪个。
根据上述,初步知道:
倍增的 2^j 一般是体现在 DP数组的最后一维的,
并且表现形式是 j
由于步长是指数形式,所以 j 的范围一般不会很大,
很有利于优化时间复杂度
j 作为最后一维度,范围一般开 18 左右
这只是个分界线
下面是其他一些运用 倍增思想的 题型
1.(倍增版)floyd()算法 o( logN * n^3 )
由于普通的floyd算法,解决不了负环问题,
当题目中没说边权的正负,但是说明了可重复经过边,
求最短路。
大概率是存在负边的。
而且题目中说了可重复经过,所以排除SPFA那样有判重数组的。
所以我们用 倍增版 floyd() 算法 (acwing 345 牛站)
下面是关于 倍增版 floyd() 算法的 代码解析:
(floyd在此处是mul,是类似于矩阵乘法的写法)