快速幂算法
假设求pow(2, 20),一次一次的累乘非常耗时间,需要进行20次运算。
将指数20使用二进制表示为10100。
则2^20 = 216*24
可以看出每当二进制位为1时将对应2的幂指数乘到结果上即可。从最低位开始迭代,在迭代时将底数进行自乘,可得到对应的幂。
而计算机存储数据时正是以二进制存储的,使用二进制不需要进行转换,对于指数需要判断它的最低位是否为1,然后将其右移一位继续判断,直到指数为0。
代码实现
double quick(double x, long long n) {
double ret = 1.0;
double base = x;
while (n > 0) {
if (n & 1) {
ret *= base;
}
base *= base;
n >>= 1;
}
return ret;
}
对应leetcode.50
完整代码
class Solution {
public:
double myPow(double x, int n) {
double ret;
long long N = n;
if(n < 0){
ret = 1 / quick(x, -N);
}
else{
ret = quick(x, N);
}
return ret;
}
double quick(double x, long long n){
double ret = 1.0;
double base = x;
while(n > 0){
if(n & 1){
ret *= base;
}
base *= base;
n >>= 1;
}
return ret;
}
};
leetcode 1922.统计好数字的数目
奇数位时有5种,偶数位有4种可能性,
为偶数是结果为 (5*4)^(n/2)
为奇数时,(5 * 4)^((n-1)/2) * 5
利用快速幂算法的同时还需要考虑结果过大的情况,利用取模的公式
(a * b) mod c = ((a mod c) * (b mod c)) mod c
防止结果超出数据范围
class Solution {
public:
static const int mod = 1000000007;
int countGoodNumbers(long long n) {
long long ret;
if(n % 2){
long long N = (n - 1) / 2;
ret = (long long)quick(20, N) * 5;
}
else{
long long N = n / 2;
ret = quick(20, N);
}
return ret % mod;
}
int quick(int x, long long n) {
long long ret = 1, base = x;
while (n > 0) {
if (n & 1) {
ret *= base;
ret %= mod;
}
base *= base;
base %= mod;
n >>= 1;
}
return ret%mod;
}
};