快速幂
如果我们要计算𝑎𝑏 mod p,我们首先能想到的便是for循环:
int ans=1;
for(int i=1;i<=b;i++)
ans*=a;
return ans%p;
下面我们来看看两个例子,想一想会出现什么奇葩结果呢?
奇葩结果1: 2100 mod 1000 = 0
奇葩结果2: 52𝑒12 mod 1000 ……

那第一个奇葩结果就是 2^100 已经溢出了。
第二个结果我们能一眼看出来,就是循环次数太多了。所以说解决这个问题O(n)是不行的。
1.解决溢出问题:
此时我们需要引进一个取模公式
(axb)%p=[(a%p)x(b%p)]%p
怎样将这个公式运用到编程里面,就需要边乘边取余,最后结果再取余
int ans=1;
for(int i=1;i<=b;i++)
ans=(ans%p * a%p)%p;
return ans;
2.降低复杂度:
引进这节课的新算法,那就是快速幂算法,是一个O(logn)
的算法,下面来讲一下递归实现和非递归实现的方式。
学快速幂之前我们需要先了解以下公式:
𝑎(𝑚+𝑛)=𝑎𝑚 *𝑎𝑛
递归实现
算法过程是将b不断地二分,先来看看两个简单的例子。
例1: 例2:
516= 58 * 58 59 = 54 * 54 *5
58 = 54 * 54 54 = 52 * 52
54 = 52 * 52 52 = 51 * 51
52 = 51 * 51 51 = 50 * 5
51 = 50 * 5
首先,我们应该知道任何数的1次方是等于它本身的,或者任何数的0次方是等于1的,所以这两个条件就可以作为递归出口的条件,下面我们来看一下代码。
ll fast_power(ll a,ll b,ll p){
if(b==0) return 1;
a%=p;
//a^(b/2)
ll c=fast_power(a,b>>1,p);
if(b&1)
return c*c%p*a%p;
return c*c%p;
}
非递归实现
非递归算法我们就要用到,幂用二进制表示,还是来看看一个简单例子
213 = 2(1101)2 = 28 * 24 * 21
思路:我们可以设置一个连乘器;将幂作为循环条件,连乘器每次乘(当前指数的二进制最低位为1时)的底数,底数一直做平方运算,n一直在除以2。先来看看下边的例子
213= 4

最低0.47元/天 解锁文章
1800

被折叠的 条评论
为什么被折叠?



