快速幂 (竞赛必备)

目录

快速幂

1.暴力

2.解决溢出问题

3.降低时间复杂度

4.代码实现

5.课后习题


快速幂

快速幂一般用来解决 a^b % c 的问题,当然计算不模c的情况也行。


1.暴力

 // 返回结果a^b % c   (c的范围一般很小所以用了int)
 public long pow(long a, long b, int c)
 {
      long res = 1;
      for (long i = 0 ; i < b; i++)
      {
          res *= a;
      }
      return res % c;
  }

这种方法对于数据范围小的情况还是可以的,但在特殊的情况下b的范围很大,例如 0 < b < 10^18

缺陷:

  • 计算中的res很容易超过long

  • 时间复杂度高 O(N)


2.解决溢出问题

取模运算有个性质:(a * b) % p = ((a % p) * (b % p)) % p

下面我们来简单证明下:

设:a = k1 * p + q1

 b = k2 * p + q2

(a * b) = (...) * p + q1 * q2

即 (a * b) % p = (q1 * q2) % p (这里不知道q1 * q2是否大于p,所以还要取模一下)

又因为 a % p = (k1 * p + q1) % p = q1

b % p = (k2 * p + q2) % p = q2

所以 (a * b) % p = ((a % p) * (b % p)) % p

但这有什么用呢?

我们之前是( a * a * ...) % c,根据这个性质我们就可以边乘边对c取摸了,这样不就解决了溢出问题了吗

即:ans *= a; ans %= c;

但还有缺陷:

  • 时间复杂度的问题没有解决


3.降低时间复杂度

先看一下我们手算3^10是怎么算的?

3^10 = (3^2)^5 = 9^5 = 9 * 9^4 = 9 * (9^2)^2 = 9 * 81^2 ....

根据上面,我们很容易发现规律:

当指数是偶数时,让指数除2,底数平方。

当指数是奇数的时候让res乘一个底数,在让指数除2,底数平方

这个算法是时间复杂度是多少? 每次让指数 b /= 2,显然是O(logN)


4.代码实现

1.详细版

 public long quickPow(long a, long b, int c)
 {
     a %= c; // 防止一开始a过大
     long res = 1; // 其实这里用int也行
     while(b > 0)
     {
         if (b % 2 == 1) // 指数是奇数
         {
             res = (res * a) % c; // 边乘边摸
             a = (a * a) % c;
             b /= 2;
         }
         else // 指数是偶数
         {
             a = (a * a) % c;
             b /= 2;
         }
     }
     return res;
 }

2.简洁版+位运算优化

 public long quickPow(long a, long b, int c)
 {
     a %= c; 
     long res = 1;
     while(b > 0)
     {
         if ((b & 1) == 1)  // b % 2 == 1
         {
             res = (res * a) % c;
         }
         a = (a * a) % c; 
         b >>= 1;   // b /= 2;
     }
     return res;
 }


5.课后习题

leetcode :

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值