快速幂(二进制理解)

一、题目背景

已知底数a,指数b,取模值mod。
求ans = a^b % mod

二、朴素算法(已知可跳过)

ans = 1,循环从 i 到 b ,每次将 ans = ans * a % mo
时间复杂度O(b)

void power(int a, int b, int mod){
    ans = 1;
    for (int i = 1; i <= b; i++) {
        ans *= a;
        ans %= mod;
    }
}

三、快速幂算法

时间复杂度O(log2b)

最近看团队老师推荐的《算法竞赛(从入门到进阶)——罗勇军 郭卫斌著》一书,对快速幂算法有新的理解,之前分奇偶情况感觉理解不是很透彻。

以 211 为例,211 可分为 28 、 22 、21三项相乘,为什么指数11是分成8、2、1呢?熟悉二进制的人应该对这三个数很熟悉,分别的23, 21, 20
恰是如此,在指数的分解上,我们可以把指数化为二进制。

(11)10 = (1011)2 = ( 23 + (0*22)+21 + 20 )10 = 8 + 2 + 1

根据红色标红式可知,只有当二进制数字为1时,分解式中对应的项才是有效的(0乘任何数都为0)。

b&1:判断二进制最右边数字是否为1
b>>1:二进制数向右移一位
二者结合,判断二进制每次更新的最右位数字是否为1。

在快速幂算法中,a更新存储的是指数b从右往左的每一项(不管指数b最右是不是1,都在一直更新,例如20,21,22,23……), 只有当b更新后的最右位是1,ans才会乘上a存储的项(可结合上面211的例子理解)

int qmod(int a, int b, int mod) {
  int ans = 1;
  a = a % mod;
  while (b > 0) {
    if (b&1) ans = (ans*a) % mod;
    b = b >> 1;
    a = (a*a) % mod;
  }
  return ans;
}
四、快速幂取模相关习题:

1. 杭电oj 1061 Rightmost Digit.
2. 杭电oj 1097 A hard puzzle.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你脸上有BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值