一、快速幂函的简单介绍:
快速幂的本质是基于 二进制和十进制的转换。
对于an 指数n都可以表示为2的指数和的形式。
比如n == 6时 , 6的二进制为(110) 6 可以表示为 1*22+1 * 21+0 * 20 (不会的可以百度二进制与十进制的转换)。
当n == 6时,
a6 == a 1*22+1 * 21+0 * 20 == a1 * 22 * a 1 * 21 * a0 * 20
其实这是一个函数a2b*(0或1)的形式(b == 0, 1, 2, 3…), 这个我们可以模拟。
并且有一规律: a2b == a2b-1* a2b-1。
对于二进制的对应位是1时 , 我们就乘上这一项,
否则, 就不乘。因为 a2b*0 == a0 == 1(1是幺元, 所以不乘没影响)。
二、代码实现:
int qpow(int a, int n)//a的 n次幂
{
int ans = 1;
while(n!= 0)
{
if(n % 2 != 0)//对于 c++ 可以改成 n&1 (会更快)
{
ans*=a;
}
a = a*a;// 模拟函数 a^2^b
n/=2;// c++ 可以改成 b>>= 1(会更快)
}
return ans;
}
cpp
代码:
int qpow(int a, int b)//a的 b次幂
{
int ans = 1;
int base = a;
while(b!= 0)
{
if(b & 1!= 0)//
{
ans*=base;
}
base*=base;// 每次利用之前计算的。
b>>= 1;
}
return ans;
}
快速幂,取模版:
ll mod_pow(ll a, ll b, ll mod)
{
ll ans =1;
ll base = a;
while(b!=0)
{
if(b%2!=0)
ans = (ans*base)%mod;
base*=base;
b/=2;
}
return ans;
}
矩阵快速幂 https://blog.youkuaiyun.com/u014634338/article/details/42467275
优势:对于求a的b次方, 如果按照一般方法循环b次相乘时间复杂度是O(b)即 O(N)级别
二快速幂的方法,会利用之前算的结果处,使杂度会降到O(log2N)(第三版块 会有证明)
三、快速幂时间复杂度证明:
大家都知道时间复杂度是主要是看循环,这个都明白,那接下来就证明快速幂的时间复杂度。
对于an:
朴素方法要循环 n 次 每次乘以a 才能得到答案——所以时间复杂度是O(n)
int ans = 1;
for(int i = 1;i <= n;i++)
{
ans*=a;
}
快速幂:
int qpow(int a, int n)//a的 b次幂
{
int ans = 1;
int base = a;
while(n!= 0)
{
if(n % 2 != 0) ans*=base;
base*=base;
n/=2;
}
return ans;
}
从代码中可知,这个循环到n == 0
而每循环一次 n要除以2。
假设k 次时 n == 0,即循环 循环了 k次, 所以要知道时间复杂度 就要求出k。
那么接下来就要求k:
n 除了 k次 2, 即 n除以 2k
所以在k-1 次时 n一定为0
即 2k-1 == n
即 k-1 == logn
k ==logn +1 ≈ logn
所以循环约了 logn 次 , 时间复杂度就为logn 级别