前言
本人第一次写博客,若有不当请见谅。
说明
平时中我们遇到一般的求幂和取模的问题,往往会想到是一个一个乘完之后再取模,但是在有的题目他的幂次和取模会很大,如果用平常的算法往往会运行时间长还有可能内存溢出导致程序无法正常运行,所以学会快速幂是必要的。
一般的求幂解法
大部分人都会想到这样解,一眼就能看明白的代码。
int fun(int n,int a)//代表为求a的n次幂
{
int sum=1;
while(n){
sum*=a;
n--;
}
return sum;
}
可以看到该基本思想的时间复杂度为O(n),这样如果n的数值大一些,在很多的程序里面就会时间超限,所以在这里我们就需要用到快速幂算法,时间复杂度即为O(logn),n是幂,大大降低了时间复杂度。
快速幂解法(迭代)
先说一下快速幂的循环解法:
关于快速幂,基本上就是由这俩个式子来推出
1)当b是奇数时,那么有 a^b = a * a^(b-1)
2)当b是偶数时,那么有 a^b = a^(b/2) * a^(b/2)
比如列举一个简单的列子:
———2的9次方
因为9是奇数 式子表示为2^9 = 2 * 2^(9-1)
如果用位运算来表示就更好说明了对于 a ^ b来说,若果把 b 写成2 进制,那么b 就可以写成若干二次幂之和,如9 的二进制 1001,于是3 号位 、0号位都是1,那么就可以得到9= 2^3 + 2^0 = 8 + 1。所以a ^ 9 = a^8 * a^1。
通过推导可以把a^b写成 a^(2 ^k)……、 a ^ 8 a ^ 4 a ^ 2 a ^ 1 等组合。
对照b的二进制时为1的位置来确定 a^(2 ^k)
以下是实现的代码和注释
int fun1(int n,int a)//代表为求a的n次幂
{
int i,sum=1;//sum代表a的n次幂,所有0次幂都是1,所以这里初值为1
while(n)//当n等于0的时候结束循环
{
if(n&1)sum=sum*a;
//当前二进制最后一位为1就乘上a
a=a*a;//对应 a^(2 ^k)
n>>=1;//每次右移一位
}
return sum;//求完后返回sum
}
快速幂取模
根据数学中的一个定理(a * b) mod c = ((a mod c)*(b mod c)) mod c
根据以上的代码只要加入要求模的数就好了
比如要求模99
int fun1(int n,int a)
{
int i,sum=1;
int b=a%99;//第一次也要模
while(n)
{
if(n&1)sum=(sum*b)%99;
b=b*b%99;
n>>=1;
}
return sum;
}