文章目录
372. 超级次方
LeetCode: 372. 超级次方
中 等 \color{#FFB800}{中等} 中等
你的任务是计算 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
方法1:递归快速幂算法
首先我们会发现次幂的结果会远远大出计算机所能表示的范围,本题中最大的数为 2147483647
的 99...9
(2000个9) 次幂。所以我们必须要找到一个简化运算的方法。
我们不妨先从流程简单的例子开始。我们取 a
为 2147483647
,也就是 <climits>
中的 INT_MAX
;b
取 2
。马上就会发现,我们要求 I N T _ M A X 2 % 1337 {INT\_MAX}^2\%1337 INT_MAX2%1337,然而 INT_MAX
的平方无法表示。所以从这里就开始出问题了,我们要找到一个更好的求余方法。
这里就会用到数学上关于余数的一些运算法则:
乘积的余数=余数的乘积(的余数)
(因为余数的乘积可能大于除数,因此还要求一次余。)
( a × b ) % x = ( ( a % x ) × ( b % x ) ) % x (a \times b) \% x=((a\%x) \times (b\%x))\%x (a×b)%x=((a%x)×(b%x))%x
这样一来,INT_MAX%1337
是可以表示出来的,然后我们将运算结果乘以自身,再对1337求余,就得到了 INT_MAX 的平方
对1337求余的结果。
余数的简化方法找到了,但是如果次幂特别大或者余数特别大,又会遇到无法表示的问题:
假设 a=1336
,b=[9]
:
1336 9 % 1337 = ( 1336 % 1337 ) 9 % 1337 = 1336 9 % 1337 {1336}^{9}\%1337=(1336\%1337)^9\%1337={1336}^{9}\%1337 13369%1337=(1336%1337)9%1337=13369%1337
可以发现,拆分过后,余数仍为1336,最后9个1336相乘仍然无法用int
来表示。
因此,我们需要对次幂进行拆分。我们可以把每2个1336单独相乘再求余:
133 6 9 % 1337 = ( 1336 2 % 1337 × 1336 2 % 1337 × ⋯ × 1336 % 1337 ) % 1337 = ( 1 × 1 × ⋯ × 1 × 1336 ) % 1337 = 1336 \begin{aligned} 1336^9\%1337 &=({1336}^{2}\%1337 \times {1336}^{2}\%1337 \times \dots \times 1336\%1337) \% 1337 \\ &= (1 \times 1 \times \dots \times 1 \times 1336) \%1337 \\ &= 1336 \end{aligned} 13369%1337