每日分享:
要相信,所有的不美好都是为了迎接美好,所有的困难都会为努力让道。
1. 作用快速幂函数是处理像 a^b%c 这类式子,当a^b特别大的时候,计算它的值就非常浪费时间和空间。
2. 如何记忆 2.1 首先知道如何计算 a^b举个例子:计算3^10
3^10 = 9^5
9^5 = 9*81^2
81^2 = 6561^1
所以 3^10 可以拆分成 9*6561^1
通过上面的拆分计算,可以减少循环的次数,降低时间复杂度(暴力计算 3^10 需要循环10次)
代码实现:
typedef long long ll;
// a=3,b=10,先忽略c
ll fast_power(ll a,ll b,ll c)
{
// 定义ans记录结果
ll ans=1;
// 指数为0时停止循环(指数为1时(ans=9,a=6561),会进入if语句中,ans=9*6561计算出来就是想要的结果了,所以说不能把循环条件改为(b!=1或b>=1),那样就得不到想要的结果了)
while(b)
{
// 指数为奇数需要提出一个底数,让指数变成偶数 ,例:(9^5 => 9*9^4)
if(b%2==1)
{
ans=ans*a;
}
// 之后进行 底^2,指数/2,例:(8^4 => 81^2)
// 底数平方
a=a*a;
// 指数整除2
b=b/2;
}
return ans;
}
2.2 对 a^b 代码稍加修改
幂模运算原理:(a * b) % c = [(a % c) * (b % c)] % c
记住下面这句话即可:
每个乘法运算再加上一个模运算(%c):这样就避免了计算9*6561这种比较大的数
typedef long long ll;
ll fast_power(ll a,ll b,ll c)
{
ll ans=1;
// 防止a比c大,降低运算难度
a%=c;
while(b)
{
if(b%2==1)
{
// 乘法运算加上模运算
ans=(ans*a)%c;
}
// 乘法运算加上模运算
a=(a*a)%c;
b/=2;
}
return ans;
}
2.3 优化代码(最终的代码)
代码中的 if(b%2==1) 和 b/=2 还可以用位运算来优化
位运算详解参考:https://blog.csdn.net/MCotoneaster/article/details/120389035
typedef long long ll;
ll fast_power(ll a,ll b,ll c)
{
ll ans=1;
a%=c;
while(b)
{
// b的二进制最后一位是1则是奇数
if(b&1)
{
ans=(ans*a)%c;
}
a=(a*a)%c;
// b二进制数右移1位(右移1位相当于除以2)
b=b>>1;
}
return ans;
}