快速幂运算
快速幂运算
- 一、快速幂运算
- 快速幂运算(Exponentiation by Squaring)
- 基本思想
- 算法实现(②③为非递归)
- ① 递归运算
- ② 普通 除模运算(不带 **模数** 与 带 **模数**)
- ③ 按位与运算
- 使用示例
- 示例代码
- 复杂度分析
- 小结论
一、快速幂运算
快速幂运算(Exponentiation by Squaring)
快速幂运算是一种高效计算 ( b^e ) 的算法,其中 ( b ) 是基数,( e ) 是指数。传统的逐步乘法方法的时间复杂度为 ( O(e) ),而快速幂运算的时间复杂度为 ( O(\log e) ),因此在处理大数时特别有效。
基本思想
快速幂运算的基本思想是利用平方和乘法来减少乘法的次数。其主要依据是:
- 如果指数 ( e ) 为偶数,则 ( b^e = (b{e/2})2 )
- 如果指数 ( e ) 为奇数,则 ( b^e = b \times b^{e-1} )
通过这种方式,可以在每次迭代中将指数减半,从而显著降低计算时间。
算法实现(②③为非递归)
以下是使用 JavaScript 实现的快速幂运算的代码:
① 递归运算
/** 不带模数
* 快速幂运算
* @param {number} base - 基数
* @param {number} exp - 指数
* @returns {number}
*/
function quickPow(base, exp) {
if (exp === 0) {
return 1; // 任何数的零次方为 1
}
if (exp % 2 === 0) {
const half = quickPow(base, exp / 2);
return half * half;
} else {
return base * quickPow(base, exp - 1);
}
}
② 普通 除模运算(不带 模数 与 带 模数)
/** 不带模数
* 快速幂运算
* @param {number} a- 基数
* @param {number} b- 指数
* @returns {number} 计算结果 (a ^ b)
*/
function quick (a, b) {
let ans = 1
while(b) { // 当指数存在的时候
// 如果指数是奇数,则要先拉出来一个底数乘到最终结果上,其余步骤和偶数一样操作
// 如果指数是偶数,则要底数平方,指数除以2(如果是使用按位与运算,则使用 "b >>= 1")b/2
if(b % 2 === 1) ans *= a
a *= a
b = Math.floor(b / 2) // 注意一定要使用Math.floor(),否则会出现小数点,导致结束循环
}
return ans
}
console.log(quick(2, 7)) // 128
/** 带模数
* 快速幂运算
* @param {number} base - 基数
* @param {number} exp - 指数
* @param {number} mod - 模数
* @returns {number} 计算结果 (base^exp) % mod
*/
const modExp = (base, exp, mod) => {
let result = 1; // 初始化结果为 1
base = base % mod; // 将基数在模数下取值
while (exp > 0) {
// 如果 exp 为奇数,将当前的 base 乘入结果
if (exp % 2 === 1) result = (result * base) % mod;
// 将 base 平方
base = (base * base) % mod;
// exp 右移,相当于整除 2
exp = Math.floor(exp / 2);
}
return result; // 返回最终结果
}
③ 按位与运算
/** 不带模数
* 快速幂运算
* @param {number} a- 基数
* @param {number} b- 指数
* @returns {number} 计算结果 (a ^ b)
*
function quick2 (a, b) {
let ans = 1
while(b) { // 当指数存在的时候
// 如果指数是奇数,则要先拉出来一个底数乘到最终结果上,其余步骤和偶数一样操作
// 如果指数是偶数,则要底数平方,指数除以2(如果是使用按位与运算,则使用 "b >>= 1")b/2
if(b & 1) ans *= a
a *= a
b >>= 1 // b右移一位
}
return ans
}
console.log(quick2(2, 8)) // 256
使用示例
快速幂运算可以用于很多应用场景,包括计算大数的幂、加密算法、以及任何需要快速计算大数时。
示例代码
const MOD = 10 ** 9 + 7; // 定义模数
console.log(modExp(2, 10, MOD)); // 输出: 1024
console.log(modExp(5, 3, MOD)); // 输出: 125
console.log(modExp(3, 7, MOD)); // 输出: 2187
console.log(modExp(10, 9, MOD)); // 输出: 1000000000
复杂度分析
- 时间复杂度: ( O(log e) ) — 每次操作将指数减半。
- 空间复杂度: ( O(1) ) — 仅使用常量级额外空间。
小结论
快速幂运算是一个非常实用且高效的算法,广泛应用于计算大数的幂以及各种算法中。了解并实现该算法可以显著提高程序运行效率,特别是在处理与模数运算相关的问题时。