快速幂

前言

本人第一次写博客,若有不当请见谅。

说明

最近在网上看了好几篇博客,也没看明白关于快速幂这个算法的时间复杂度是怎么优化的,这让数学差的人使劲挠头,后面又看了几篇快速幂的代码和思路,终于完全搞明白快速幂到底是个什么算法,下面写的是我个人对快速幂的看法和见解,关于原理的解释如果有错误请一定要评论我改正!

一般的求幂解法

基本思想就是乘以n次的a

int fun(int n,int a)//代表为求a的n次幂 
{
	int sum=1;
	while(n)
	{
		sum*=a;
		n--;
	}
	return sum;
}

可以看到该基本思想的时间复杂度为O(n),这样如果n的数值大一些,在很多的程序里面就会时间超限,所以在这里我们就需要用到快速幂算法,时间复杂度即为O(logn),n是幂,大大降低了时间复杂度。

快速幂解法(循环)

先说一下快速幂的循环解法:
关于快速幂,博主的主要理解就是分开相乘,即为an=(a2)^n/2
比如列举一个简单的列子:

———2的9次方

因为9/2等于4,因为c语言的向下取整会失去一次幂所以

当(此列子9为n)n为不是2的倍数时就用最终结果表示变量sum将他乘起来。

n的次方就相当于an=a*an-1,而a的一次方已经被sum乘起来所以n直接减去1就可以了。

此时就可以将a的值变为a2,n的值变为n/2;即分开相乘,因为是向下取整,所以上面的

n-1可以省略掉。

不多说了,直接上代码加注释,希望各位读者结合注释和上面的解释阅读和理解。

int fun1(int n,int a)//代表为求a的n次幂 
{
	int i,sum=1;//sum代表a的n次幂,所有0次幂都是1,所以这里初值为1 
	while(n)//当n等于0的时候结束循环 
	{
		if(n%2!=0)sum=sum*a;
		//当n为单数时候就让sum和a相乘一次,就相当于a^n=a*a^(n-1)
		//n不需要减去1是因为int类型是向下取整 
		a=a*a;//a^n=(a^2)^(n/2),a此时就变为a^2 
		n/=2;//n此时就变为n/2 
	}
	return sum;//求完后返回sum 
}

快速幂解法(递归)

关于快速幂的递归写法是基于上面循环的思想改为递归,和上面思想基本一致。

首先要有递归结束条件,如果所求的n次幂为0次幂就直接返回1即可,因为所有数的0次幂都是1。

然后再后再考虑不是0的情况

如果n不是2的倍数也就是让此时的a和上次递归的返回值相乘这里的n需要减去1如果不减去1他

就会一直不是2的倍数,一直递归,死递归了。如果是2的倍数就进行下一次递归,传进去的值

就为a2和n/2。

此时也需要一个结束递归的条件,就是当n等于1的时候,就已经将n次幂的值都存进了a里面,直接返回即可。

int fun2(int n,int a)//代表为求a的n次幂 
{
	if(n==0)return 1;//如果n是0,就是任何数的0次幂都是1 
	if(n==1)return a;//当n为1的时候就要结束递归了,返回a 
	else
	{
		if(n%2==1)return fun2(n-1,a)*a;
		//此时也是当n为单数时候就让上次的返回值和a相乘一次
		return fun2(n/2,a*a);//此时a传进去下次递归为a^2,n为n/2 
	}
}

快速幂取模解法

基于以上的快速幂循环和递归的解法里面将所有赋值a和sum的时候取模一个需要被取模的值即

可,此处假设需要取模的值为123。

循环代码为:

int fun1(int n,int a)//代表为求a的n次幂 
{
	int i,sum=1;
	while(n)
	{
	if(n%2!=0)sum=sum*a%123;
	a=a*a%123;
	n/=2;
	}
	return sum;
}

递归代码为:

int fun2(int n,int a)
{	
	     if(n==0)return 1;
	     if(n==1)return a%123;
	     else   
	     {    
	     	     if(n%2==1)return fun2(n-1,a)*a%123;
	     	     return fun2(n/2,a*a%123);  
	     } 
} 

此处取模是根据此公式:(ab)%c=((a%c)(b%c))%c 得来的,因为看快速幂的原理还是乘积,所以要在每个乘积的值后面取模。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值