暴力破解
我们很容易想到 可以采用 b 个 a 相乘来求结果。
但此种方法需要大量计算,时间复杂度为 。
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
long long ans = 1;
cin >> a >> b;
for (int i = 0; i < b; ++i) {
ans *= a;
}
cout << ans << endl;
return 0;
}
快速幂算法
当我们计算 次方的时候可以利用 。
这样每次我们只需要把指数 a 减少一半,底数 b 变为原来的平方即可大大减少循环的次数。
当指数为偶数时,每次把指数 b 缩小为原来的一半,底数 a 变为原来的平方。
当指数为奇数时,我们可以指数 b 减一,结果乘以底数 a 。再按照偶数的规则进行运算即可。
这样快速幂算法的时间复杂度为: 。
普通代码
我们每次循环,根据指数 b 为奇数还是偶数分别进行计算。
当输入的指数 b 为偶数时,每次循环指数 b 变为原来的一半,偶数除以 2 仍为偶数。 这样指数 b 在最后一次循环时会变为 1 ,此时即可算出结果。
当输入的指数 b 为奇数时,每次循环指数 b 减一。 这样指数 b 变成了偶数,随后即可按照偶数规则进行计算。
- 当前指数 b 为奇数,把指数
b--,结果ans *= a。 - 当前指数 b 为偶数,把指数
b /= 2,底数a *= a。
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
long long ans = 1;
cin >> a >> b;
while (b) {
if (b % 2 == 1) {
b--; ans *= a;
} else {
b /= 2; a *= a;
}
}
cout << ans << endl;
return 0;
}
优化代码
上述代码可以进行优化
- 我们可以使用
b & 1来判断该数字的奇偶性,此代码可以获指数 b 二进制的最后一位,根据二进数的表示规则,当b & 1 = 1时,该数为奇数,当b & 1 = 0时,该数为偶数。 - 利用
b >> 1代替b / 2 - 当指数 b 为奇数时,当减一后可以直接按照偶数规则进行运算。因此,每次循环我们可以直接右移一位即可,可以减少一次循环次数。
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
long long ans = 1;
cin >> a >> b;
while (b) {
if (b & 1) {
b--; ans *= a;
}
b >>= 1; a *= a;
}
cout << ans << endl;
return 0;
}
相关题目
题目 Pow(x, n)
此题需注意 n 的取值范围为:,因此需要注意 n 为负数的情况。
当 n 为负数时,,因此当我们计算负数时,可以先把指数 b 转为正数,再用 1 除以结果,即可得到最终结果。
注意:当n = INT_MIN时,-n 会越界,因此我们先把 n 转为long long类型,再转为负数。
class Solution {
public:
double myPow(double x, int n) {
long long power = n >= 0 ? n : -(long long) n;
double ans = 1.0;
while (power != 0) {
if (power & 1) {
ans = ans * x;
}
power >>= 1; // equal to power /= 2;
x = x * x;
}
return n >= 0 ? ans : 1.0 / ans;
}
};
题目 a^b
此道题目只需要返回 后的结果。如果得到结果后再 ,如果数据过大则会导致越界。
因此可以利用 (a * b * c) % p = ((a % p) * (b % p) * (c % p)) % p 来计算。
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b, p, ans = 1;
cin >> a >> b >> p;
while (b) {
if (b & 1) {
--b; ans = (long long) ans * a % p;
}
b >>= 1; a = (long long) a * a % p;
}
cout << ans % p<< endl;
return 0;
}
题目 64位整数乘法
链接:AcWing 90. 64位整数乘法 我们可以利用快速幂的思路来求解大整数的乘法。
- 当 b 为奇数的时候,我们可以减一,结果加上 a 。
- 当 b 为偶数的时候,我们把 a 扩大2倍,b 变为原来的一倍。
注意:当 a 为奇数的时候,我们可以不减一,而是利用C++除法的向下取整来代替减一。例如: ,相当于先减去一,再进行除以 2 ,因此此步只需除以 2 即可。
#include <bits/stdc++.h>
using namespace std;
unsigned long long a, b, p, ans;
int main() {
cin >> a >> b >> p;
while (b) {
if (b & 1) ans = (ans + a) % p;
a = a * 2 % p;
b >>= 1;
}
cout << ans << endl;
return 0;
}