乘法快速幂相关总结 & LeetCode - 50. Pow(x, n)
- 递归计算 (a n) % mod
- 非递归计算 (a n) % mod
- 计算 ( a * b ) % mod
- 配合 ( a * b ) % mod和乘法快速幂
- XYNUOJ - 1872. 次方求模题解
- LeetCode - 50. Pow(x, n)题解
递归计算 (a n) % mod
递归计算其实是更容易理解的:
- 为了求an,我们先递归去求出an/2,得到结果记录为
halfRes
; - 然后如果
n
为偶数,很好办,再乘以一个halfRes
就可以了(再取模一下),也就是可以返回halfRes*halfRes
; - 但是如果
n
为奇数的话,就需要再乘以一个a
,然后再返回;
代码:
1 | static long pow_mod(long a, long n, long mod) { |
非递归计算 (a n) % mod
假设一个整数是10
,如何最快的求解10
的75
次方。
- ①
75
的二进制形式为1001011
; - ②
10
的75
次方 = **1064 × 108 × 102 × 101**; - 在这个过程中,我们先求出101,然后根据101求出102,再根据102求出104。。。。,最后根据1032求出1064,即
75
的二进制数形式总共有多少位,我们就使用了多少次乘法; - ③ 在步骤②进行的过程中,把应该累乘的值相乘即可,比如**1064、108、102、101应该累乘,因为
64、8、2、1
对应到75
的二进制数中,相应位上是1
;而1032、1016**、104不应该累乘,因为32、16、 4
对应到75
的二进制数中,相应位是0
;
1 | static long pow_mod2(long a, long n, long mod) { |
使用a ^ 11
来模拟一下计算过程:
计算 ( a * b ) % mod
1 | // 计算 (a * b) % mod |
配合 ( a * b ) % mod和乘法快速幂
可以使用非递归的乘法快速幂和上面的 (a*b) % mod
来计算快速幂,差别不大:
1 | // 计算 (a * b) % mod |
XYNUOJ - 1872. 次方求模题解
题目链接
题目
完全的模板题,三种方法都可以通过:
1 | import java.io.BufferedInputStream; |
LeetCode - 50. Pow(x, n)题解
题目链接
题目
解析
这个题目和普通的求幂不同的是:
- 其中
x
(底数)是double
类型的,且n
是范围是Integer
范围的(可正可负) : - 要注意的就是当
n
为负数的时候,我们可以转换成求1.0 / pow(x,-n)
; - 还一个很重要的地方就是当
n = Integer.MIN_VALUE
的时候要特殊处理,因为整形范围是-231到231-1,所以或者我们使用long
来存转换的数,或者特殊判断一下;递归求解:
两种写法意思一样,第二种写法更加简洁:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22class Solution {
public double myPow(double x, int n) {
if (n > 0) {
return pow(x, n);
} else {
if (n == Integer.MIN_VALUE) {
return 1.0 / (pow(x, -(Integer.MIN_VALUE + 1)) * x); // MAX_VALUE = -(Integer.MIN_VALUE + 1)
}
return 1.0 / pow(x, -n);
}
}
public double pow(double x, int n) {
if (n == 0)
return 1;
double half = pow(x, n / 2);
if (n % 2 == 0)
return half * half;
else
return x * half * half;
}
}
1 | class Solution { |
非递归求解:
三种写法的意思都是一样,只不过处理Integer.MIN_VALUE
的方式不同而已。
1 | class Solution { |
1 | class Solution { |
1 | class Solution { |