传统解法
我们知道求一个数的幂可以表示为(ab)意思是a的b次方。如28运算结果是256运用for循环8次完全可以得到正确结果,但当b的值为10000,1000000时我们要得到幂函数的结果就相当麻烦了,那么是否有一种简单的方法可以使我们迅速得到幂函数的结果呢? 这就是今天我们要介绍的快速幂算法!
快速幂简介
如28可以等价于((((22)2)2)2),这时只需进行四次运算就可以得到本需要八次运算才可以得到的结果,在b数值较小的情况下我们不能较为直接的感觉到快速幂算法的优异性,但当b为10000甚至更大时速度会大大提高,减少时间复杂度一半。如当b=100000时,运用快速幂算法,直接减少了50000次运算,效率大大提高。
代码实现
当b为偶数时,它可以被分成一个个相同的(2)次模块。但当b为奇数时,b-1为偶数,算出结果后再乘以自身就可以得到运算结果。
long long fastPower(long long base, long long power) {
long long result = 1;
while (power > 0)
{
if (power % 2 == 0)//如果指数为偶数
{
power = power / 2; //把指数缩小为一半
base = base * base ;//底数变大成原来的平方
}
else //如果指数为奇数
{
power = power - 1;//把指数减去1,使其变成一个偶数
result = result * base ;//此时记得要把指数为奇数时分离出来的底数的一次方收集好
power = power / 2;//此时指数为偶数,可以继续执行操作
base = base * base ;
}
}
return result;
}
拓展
现在我们来看这个例题点击此处
此题要求 ,求ab的后三位。当b的值充分大时,因为指数增长的缘故,即使long long也不能存下所有的结果。
所可以根据以下“取模”运算法则对代码进行优化
1. (a + b) % p = (a % p + b % p) % p (1)
2. (a - b) % p = (a % p - b % p ) % p (2)
3. (a * b) % p = (a % p * b % p) % p (3)
优化后
long long fastPower(long long base, long long power) {
long long result = 1;
while (power > 0) {
if (power % 2 == 0) {
//如果指数为偶数
power = power / 2;//把指数缩小为一半
base = base * base % 1000;//底数变大成原来的平方
} else {
//如果指数为奇数
power = power - 1;//把指数减去1,使其变成一个偶数
result = result * base % 1000;//此时记得要把指数为奇数时分离出来的底数的一次方收集好
power = power / 2;//此时指数为偶数,可以继续执行操作
base = base * base % 1000;
}
}
return result;
}
终极优化
借鉴一位大佬
原文链接: https://blog.csdn.net/qq_19782019/article/details/85621386
正文
在C语言中,power%2==1可以用更快的“位运算”来代替,例如:power&1。因为如果power为偶数,则其二进制表示的最后一位一定是0;如果power是奇数,则其二进制表示的最后一位一定是1。将他们分别与1的二进制做“与”运算,得到的就是power二进制最后一位的数字了,是0则为偶数,是1则为奇数。例如5是奇数,则5&1=1;而6是偶数,则6&1=0;因此奇偶数的判断就可以用“位运算”来替换了。
同样,对于power=power/2来说,也可以用更快的“位运算”进行替代,我们只要把power的二进制表示向右移动1位就能变成原来的一半了。
最终结果
long long fastPower(long long base, long long power) {
long long result= 1;
while (power > 0) {
if (power & 1) {//此处等价于if(power%2==1)
result = result * base % 1000;
}
power >>= 1;//此处等价于power=power/2
base = (base * base) % 1000;
}
return result;
}
通过实验可得最终运算速度接近于零,可以看出快速幂算法是一种高效成熟的算法。
第一次写博客,完全懵 B;