【令人心动的算法】快速幂
本文最后更新于100 天前,其中的信息可能已经过时,如有错误请发送邮件到727189340@qq.com

快速幂旨在 $O(\log_2 N)$ 次的时间复杂度下计算 $a ^ n$ 的结果,相比于传统 $O(N)$ 的暴力写法更加高效。

原理

以计算 $a ^ {11}$ 为例。

我们可以先将这个数拆分,保证每一个指数都是 $1$ 或 $2$ 的倍数,例如,$a ^ {11} = a ^ {8 + 2 + 1} = a ^ 8 \times a^2 \times a ^ 1$。

这样做运用了倍增的思想:只要知道 $a$,就可以知道 $a ^2$,再乘以自身就可以知道 $a ^ 4$……

那么我们如何找出这个拆分的方式呢?想到二进制:将 $11$ 转化成二进制:$11_{10} = 1011_2 = 2^3 + 2^1 + 2^0 = 8 + 2 + 1$。这就是我们最后要拆分出来的结果。

要更好地计算二进制,就可以运用位运算。可以得到快速幂的代码。

快速幂模板

P1226 【模板】快速幂

#include <iostream>
#define ll long long

using namespace std;

ll fastPow(ll a, ll n, ll mod)
{
    ll ans = 1;
    a %= mod;
    while(n)
    {
        if (n & 1) // 判断二进制最后一位是不是 1
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        n >>= 1;
    }
    return ans;
}

局限性

如果 $a$ 太大,即使是快速幂也会出现溢出的情况。这时候需要使用高精度,或者 Python 来进行运算。但这会显著降低运行效率。

如果 $n$ 太大,例如 $10 ^ {200000000}$,即使是 $O(\log_2 N)$ 的时间复杂度也会出问题,这时候就需要使用更复杂的写法:扩展欧拉定理。

扩展欧拉定理模板:计算 n 极大时的快速幂

P5091 【模板】扩展欧拉定理

(本题需要求 $a ^ b \mod m$ 的结果,下文中所有的描述将以这三个字母作为命名。)

欧拉定理的内容不在此文中赘述。其时间复杂度可以认为是 $O(len_b + \sqrt m + \log_2 m)$。

#include <iostream>
#define ll long long

using namespace std;

ll euler_phi(ll n)
{
    ll ans = n;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0)
        {
            ans = ans / i * (i - 1);
            while (n % i == 0)
                n /= i;
        }
    if (n > 1)
        ans = ans / n * (n - 1);
    return ans;
}

ll fast_pow(ll a, ll n, ll mod)
{
    ll ans = 1;
    a %= mod;
    while (n)
    {
        if (n & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        n >>= 1;
    }
    return ans;
}

ll read(ll mod)
{
    ll x = 0, w = 1;
    char ch = 0;
    bool check = false;
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = ((x << 3) + (x << 1) + (ch - '0'));
        if (x >= mod)
        {
            check = true;
            x %= mod;
        }
        ch = getchar();
    }
    if (x >= mod)
    {
        check = true;
        x %= mod;
    }
    if (check)
        x += mod;
    return x * w;
}

作者

觉得有帮助的话可以投喂煮啵,助力煮啵过上点外卖不用神卷的生活

本文作者:Flaw_Owl
看到这里的朋友们,作者十分感谢!如果你看到任何写得不清楚或是错误之处,或者是有什么希望看到的课程和内容笔记,欢迎在评论区留言!评论区可以单纯的发表文字,也可以使用 Markdown 语法,你可以参照 Markdown 官方教程发出带有格式的评论。

版权说明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0协议,转载请注明文章地址及作者哦
暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇