题目
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/super-pow
你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。
示例 1:
输入:a = 2, b = [3]
输出:8
示例 2:
输入:a = 2, b = [1,0]
输出:1024
示例 3:
输入:a = 1, b = [4,3,3,8,5,2]
输出:1
示例 4:
输入:a = 2147483647, b = [2,0,0]
输出:1198
提示:
1 <= a <= 231 - 1
1 <= b.length <= 2000
0 <= b[i] <= 9
b 不含前导 0
解法
-
如果使用暴力算法,先将后面的数组拼接为整数,之后再求幂指数,会提示超时
-
幂指数解法有一个关于快速幂的内容,即将 a n a^n an拆分为 a n / 2 ∗ a n / 2 a^{n/2} * a^{n/2} an/2∗an/2, 然后判断n的奇偶数,看看是否需要再乘以一个a
-
另外列表元素组合成一个整数也可以拆成求和的形式, a 121 = a 100 + a 20 + a 1 a^{121} =a^{100}+a^{20}+a^{1} a121=a100+a20+a1的样式,因此,列表元素如果取反之后,然后遍历的时候,每个元素遍历完再乘以10就能模拟这种大数了
-
“整除分配律”: ( a ∗ b ) % m o d = ( a % m o d ) ∗ ( b % m o d ) % m o d (a*b)\% mod = (a\%mod) * (b\%mod) \% mod (a∗b)%mod=(a%mod)∗(b%mod)%mod
-
python
MOD = 1337
class Solution:
def superPow(self, a: int, b: List[int]) -> int:
res = 1
x = a % MOD
for y in b[::-1]:
res = (res * self.quickPow(x, y)) % MOD
x = self.quickPow(x, 10)
return res
def quickPow(self, x: int, n: int) -> int:
res = 1
while n:
if n % 2 == 1:
res = (res * x) % MOD
n >>= 1
x = (x * x) % MOD
return res
- c++
class Solution {
const int MOD = 1337;
public:
int quickPow(int x, int n)
{
int res = 1;
x = x % MOD;
while(n)
{
if(n&1)
{
res = (long) res * x % MOD;
}
x = long (x*x) % MOD;
n >>= 1;
}
return res;
}
int superPow(int a, vector<int>& b) {
int nSize = b.size();
int res = 1;
for(int i=nSize-1; i>=0; i--)
{
res = (long) res * quickPow(a, b[i]) % MOD;
a = quickPow(a, 10);
}
return res;
}
};
复杂度分析
- 时间复杂度:
- O ( l o g K ) O(logK) O(logK) 假设 b 数组所代表的数字为 K,使用快速幂的复杂度为 O ( l o g K ) O(logK) O(logK),或者说是 O ( n ∗ log 10 ) O(n * \log{10}) O(n∗log10),其中 n 为数组 b 的长度,数字 10 所代表的含义是计算一个次方为 10 以内的值;而不使用快速幂的复杂度为 O ( n ∗ 10 ) O(n*10) O(n∗10)
- 空间复杂度
- O ( 1 ) O(1) O(1)