算法详解1——快速幂
前言
快速幂是一个可以快速算出
目录
-
快速幂的概念及过程
-
代码实现
第一部分:快速幂的概念及过程
正常情况下,如果我们要计算
a^b ,那么我们会直接循环b 次,每次乘上a ,代码如下:int res=1; for (int i=1;i<=b;i++) res*=a;
但这种算法的时间复杂度是
在讲速幂之前,我们先得明确一个概念:
a^{b+c}=a^b\cdot a^c
证明很简单,因为
明确完这个,咱们再想想,根据二进制原理,每个整数都可以拆分成
8=2^3
10=2^3+2^1
15=2^3+2^2+2^1+2^0
那么,如果我们把
2^{15}=2^{2^3+2^2+2^1+2^0}
在根据刚刚讲的第一个概念,可以转换成:
2^{2^3+2^2+2^1+2^0}=2^{2^3}\cdot 2^{2^2}\cdot 2^{2^1}\cdot2^{2^0}
我们又知道:
2^{2^1}=(2^{2^0})^2
2^{2^2}=(2^{2^1})^2
2^{2^3}=(2^{2^2})^2
即:
a^{2^b}=(a^{2^{b-1}})^2
所以我们可以设定一个变量
2\cdot 2^2\cdot 2^{2^2}\cdot 2^{2^{2^2}} = 2\cdot 4\cdot 16\cdot 256 = 32768
所以
2^{15}=32768
由此,我们总结出了快速幂的基本步骤:对于
这样做的时间复杂度是多少呢?因为我们只需要一个拆解成二进制的循环,复杂度为
第二部分:代码实现
代码如下:
int pw(ll a,ll b,ll p)//p是模数,因为有时候答案可能爆long long,所以要取摸p
{
int res=1,tmp=a;//初始值
while (b>0)//二进制分解
{
if (b%2)//如果是1
{
res*=tmp;
res%=p;//防止爆long long,取模p
}
tmp=tmp*tmp;//tmp自乘
tmp%=p;
b/=2;
}
return res;
}
推荐题目:
P1226 【模板】快速幂
结语
快速幂的知识点就讲到这了。这是本蒟蒻第一次发算法解析,若其中有错误之处,欢迎大家指出!
本人洛谷号(欢迎关注)