【算法学习笔记】倍增

倍增

倍增是一种非常重要的思想,在 ACM/OI 中有着丰富的应用。

倍增的本质可以表述为,对于一种操作f(x),通过计算f(x),f2(x),f4(x),,f2k(x)来加速求解fn(x)。假设f(x)的时间复杂度为O(1),那么直接计算fn(x)的时间复杂度为O(n),而通过倍增的方法,则可以加速到O(logn)

快速幂

快速幂是倍增最常见的应用场景。所谓快速幂,指的是快速求解数x在模m意义下的幂xymodm

递归求解

比较直接的想法是递归进行求解。很容易得到下面的递归式:

xy={1y=0(xy2)2y为大于0的偶数(xy12)2xy为大于0的奇数

模板题:洛谷P1226

注意使用 long long 保证数据不溢出

Code(C++)
#include <iostream>
using namespace std;
using ll = long long;
int qpow(int b, int p, int k) {
    if (p == 0) return 1 % k;
    int half = qpow(b, p / 2, k);
    int ans = (ll)half * half % k;
    if (p & 1) ans = (ll)ans * b % k;
    return ans;
}
// 求 b^p mod k
int main() {
    int b, p, k;
    cin >> b >> p >> k;
    cout << b << "^" << p << " mod " << k << "=" << qpow(b, p, k);
    return 0;
}

递归方法对于快速幂已经足够,但其缺乏足够的普适性,无法推广到更加一般性的问题。

迭代求解

与递归方法相比,迭代方法的思想更加贴近倍增方法的本质。利用xy=xi=0kci2i,我们可以从x1,x2,,x2k来计算出xy,而这些数值本身是可以通过反复进行平方运算在O(k)=O(logy)的时间内求得的。这里我们需要得到一个非负整数的二进制表示(从低位到高位),只需要不断除以2取余即可。

模板题:洛谷P1226

注意使用 long long 保证数据不溢出

Code(C++)
using ll = long long;
int qpow(int a, int b, int k) {
    int ans = 1 % k;
    for (; b; b >>= 1, a = (ll)a * a % k)
        if (b & 1) ans = (ll)ans * a % k;
    return ans;
}
// 求 b^p mod k
int main() {
    int b, p, k;
    cin >> b >> p >> k;
    cout << b << "^" << p << " mod " << k << "=" << qpow(b, p, k);
    return 0;
}

倍增思想的推广

快速乘

将快速幂中的乘法运算替换为加法运算,我们就可以得到快速乘的算法,也即用O(logn)次加法运算来实现乘n的操作。

快速乘模板代码:

// 迭代实现
inline ll ksc(ll x, ll y, ll mod) {
    ll res = 0;
    for (; y; y >>= 1, x = (x << 1) % mod)
        if (y & 1) res = (res + x) % mod;
    return res;
}

// O(1)快速乘
typedef long long ll;
typedef unsigned long long ull;
typedef long double lb;
//代码压缩
inline ll Ksc(ull x, ull y, ll p) {  
    return (x * y - (ull)((lb)x / p * y) * p + p) % p;
}

矩阵快速幂

将快速幂中的底数改为一个方阵,并将整数乘法改为矩阵乘法,我们就可以得到矩阵快速幂的算法。

倍增法求LCA

如果把f(x)看作是求取x的父节点,那么fn(x)就可以是看成求取xn代的祖先节点。倍增法求LCA的关键就是用倍增方法来快速求取fn(x)

稀疏表

稀疏表是一种用于RMQ(区间最值查询)的数据结构。稀疏表的构建同样使用了倍增的思想。

posted @   RioTian  阅读(1865)  评论(0编辑  收藏  举报
编辑推荐:
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
阅读排行:
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 5. Nginx 负载均衡配置案例(附有详细截图说明++)
点击右上角即可分享
微信分享提示

📖目录