快速幂算法

文章介绍了快速幂算法,用于高效计算x^n的值。通过递归和循环两种基本方法,然后提出快速幂算法,将时间复杂度降低到O(logn)。文章详细解释了算法原理,包括如何利用二进制分解来优化计算,并提供了不同进制版本的算法实现,强调了并不总是进制越高越好,最终推荐了使用二进制优化的版本作为最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

快速幂算法

设计一个算法计算 x n x^n xn的值。

根据定义最常见也最能瞬间想到的是如下的算法:

// 递归写法
public int pow1(int x, int n) {
   
  if (n == 0) return 1;
  if (n == 1) return x;
  return x * pow1(x, n - 1);
}
// 循环写法
public int pow2(int x, int n) {
   
  int y = 1;
  while (n) {
   
    y *= x;
    n--;
  }
  return y;
}

但上面的算法的时间复杂度是 O ( n ) O(n) O(n)

下面采用快速幂算法来解决这个问题。

在解决它之前先来看一下原理: x n = x n − a x a x^{n}=x^{n-a}x^a xn=xnaxa

所以我们可以对本身要求的 x n x^n xn对半分来求,只求一半的数,然后乘以自己本身就可以达到 x n x^n xn

但是会出现的情况就是,对半分的时候会出现小数的情况,所以一定要分奇数和偶数的情况。

如果n分半了之后是偶数,那就直接对半分,如果是奇数则在对半分之后还要乘以一个x。

所以可以有下面的规律:

f(x, n) = {
   
  f(x, n/2)*f(x, n/2),    // 当n为偶数
  x*f(x, n/2)*f(x, n/2)   // 当n为奇数
}

所以得出快速幂算法1:

public int qPow1(int x, int n) {
   
  if (n == 0) return 1;
  if (n == 1) return x;
  if (n % 2 == 1) return x*f(x, n/2)*f(x, n/2);
  return f(x, n/2)*f(x, n/2);
}

但是上面的算法明显没有任何增进,因为f(x, n/2)要算两次,那和之前的 O ( n ) O(n) O(n)的算法没什么区别。所以使用一个中间变量去接受一下,就可以提高算法效率。

public int qPow1(int x, int n) {
   
  if (n == 0) return 1;
  if (n == 1) return x;
  int t = f(x, n/2)
  if (n % 2 == 1) return x * t * t;
  return t * t;
}

上面的快速幂算法还是比较好理解的,下面的快速幂算法就比较的炫技了我觉得,但是也就那样(原理还是上面的,只是不是对半分而已,而是根据进制数来分)。

下面采用二进制数来分。

假设我们要计算的是 x 10 x^{10} x10,那么10的二进制数是1010,所以有如下公式及变换: x 10 = x ( 10 ) 10 = x ( 1010 ) 2 = x 1 ∗ 2 3 + 0 ∗ 2 2 + 1 ∗ 2 1 + 0 ∗ 2 0 = x 8 + 2 = x 8 x 2 x^{10}=x^{(10)_{10}}=x^{(1010)_2}=x^{1*2^3+0*2^2+1*2^1+0*2^0}=x^{8+2}=x^8x^2 x10=x(10)10=x(1010)2=x123+022+121+02

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值