题目来源:LeetCode 372. 超级次方
问题抽象: 给定一个正整数 a
和一个用数组 b
表示的非常大的正整数(数组元素依次为十进制表示的每一位),计算 a^b mod 1337
的值,满足以下核心需求:
-
核心计算:
- 结果需为
a
的b
次方对1337
取模(即(a^b) % 1337
); - 指数
b
以数组形式给出(如b=[1,2,3]
表示123
),长度可能极大(最大2000
)。
- 结果需为
-
优化目标:
- 避免直接计算大指数(
b
可达10^2000
量级),需通过 快速幂 和 模运算性质 分解计算:- 逐位分解:利用公式
a^b = (a^b)^10 * a^d mod 1337
(b'
为b
去掉末位的数,d
为末位); - 递归/迭代:从数组末位(个位)向高位递推计算。
- 逐位分解:利用公式
- 避免直接计算大指数(
-
数学性质:
- 模运算恒等式:
(x * y) mod 1337 = [(x * 1337) * (y mod 1337)] mod 1337
; - 快速幂:计算
a^d mod 1337
时(d
为单数字),时间复杂度 O(log d)。
- 模运算恒等式:
-
边界处理:
- 指数为
0
:若b=[0]
,则a^0=1
(但题目保证b
为正整数,通常不出现); - 底数取模:先对
a
取模(a %= 1337
)简化计算; - 特殊值:
a=1
时结果为1
;a=0
时结果为0
(除非b=0
)。
- 指数为
-
计算约束:
- 时间复杂度 O(n log d):
n
为b
的长度(位数),d
为单数字最大值9
(快速幂最多4
步); - 空间复杂度 O(1)(迭代)或 O(n)(递归栈);
- 输入范围:
1 ≤ a ≤ 2^31-1
;b
数组长度[1, 2000]
,元素值0-9
(首位非0
)。
- 时间复杂度 O(n log d):
输入:正整数 a
,整数数组 b
(表示指数)
输出:a^b mod 1337
(整数)。
解题思路
题目要求计算 a^b mod 1337
,其中 a
是正整数,b
是以数组形式给出的超大正整数(数组长度最大2000)。直接计算指数不可行,需结合模运算性质和快速幂算法:
-
模运算性质:
(x * y) mod 1337 = [(x mod 1337) * (y mod 1337)] mod 1337
,可在计算过程中不断取模防止溢出。 -
指数分解:
设b = [b₀, b₁, ..., bₖ₋₁]
表示数字n = b₀*10^(k-1) + b₁*10^(k-2) + ... + bₖ₋₁
,则:
a^n = a^(b₀*10^(k-1)) * a^(b₁*10^(k-2)) * ... * a^(bₖ₋₁)
利用公式a^(m+n) = a^m * a^n
和a^(m*n) = (a^m)^n
分解计算。 -
快速幂算法:
高效计算a^k mod 1337
,时间复杂度O(log k)
。将指数转为二进制,通过平方和乘法减少计算次数。 -
逐位处理(从低位到高位):
- 初始化结果
res = 1
。 - 从数组末位(个位)开始向前遍历:
- 计算
a^(当前位数值) mod 1337
,乘到res
上。 - 更新
a = a^10 mod 1337
(为下一位的十位权重做准备)。
- 计算
- 遍历结束后
res
即为最终结果。
- 初始化结果
时间复杂度:O(n),其中 n 是数组长度。每轮循环执行常数次快速幂操作(指数最大10)。 空间复杂度:O(1),仅用常数额外空间。
代码实现(Java版)🔥点击下载源码
class Solution {
private static final int MOD = 1337; // 常量模数
public int superPow(int a, int[] b) {
int res = 1;
a %= MOD; // 初始取模,避免后续乘法溢出
for (int i = b.length - 1; i >= 0; i--) {
// 计算当前位的贡献:a^(b[i]) mod MOD
res = res * quickPow(a, b[i]) % MOD;
// 更新底数:a^10 mod MOD(为下一位的十位权重做准备)
a = quickPow(a, 10);
}
return res;
}
// 快速幂计算:base^exponent mod MOD
private int quickPow(int base, int exponent) {
int result = 1;
base %= MOD; // 确保base在模范围内
while (exponent > 0) {
if ((exponent & 1) == 1) { // 指数当前位为1
result = (result * base) % MOD; // 乘入结果
}
base = (base * base) % MOD; // 底数平方
exponent >>= 1; // 指数右移(除以2)
}
return result;
}
}
代码说明
-
主函数
superPow
:- 初始化结果
res=1
,对a
预取模防止后续溢出。 - 倒序遍历数组
b
(从个位到高位):- 调用
quickPow(a, b[i])
计算当前位的贡献,累乘到res
并取模。 - 更新底数
a = a^10 mod MOD
(为下一位的十位权重做准备)。
- 调用
- 返回最终结果
res
。
- 初始化结果
-
快速幂函数
quickPow
:- 通过二进制分解指数,循环处理:
- 若指数当前位为1,将当前底数乘入结果。
- 底数平方后取模,指数右移一位。
- 时间复杂度
O(log exponent)
,确保高效计算大指数幂。
- 通过二进制分解指数,循环处理: