快速幂:
前置知识:分治
快速幂是用来求解
$$a^b$$
的一种基于分治的算法。
首先根据我们学过的同底数幂乘法,显然有
$$a^b=a^{\frac{b}{2}}\times a^{\frac{b}{2}}$$
但是$\frac{b}{2}$有可能是小数啊QAQ,这样的话不就更麻烦了吗?
考虑分类讨论:
当$b$为偶数时,这样的话$\frac{b}{2}$为整数,故此时:
$$a^b=a^{\frac{b}{2}}\times a^{\frac{b}{2}}$$
当$b$为奇数时,这样的话可以将$\frac{b}{2}$看作$\lfloor\frac{b}{2}\rfloor$,但是我们发现这样的话最终的指数位置会少一个$1$,所以最终答案我们多乘上一个$a$就行了:
$$a^b=a^{\lfloor\frac{b}{2}\rfloor}\times a^{\lfloor\frac{b}{2}\rfloor}\times a$$
然后这就是快速幂的基本原理啦,是不是非常简单呢(((
接下来我们可以写出递归版代码:
ll ksm(ll b,ll p){ if(!p) return 1; if(p==1) return b%mod; ll t=ksm(b,p/2)%mod; if(n&1) return b*t*t%mod; else return t*t%mod; }
但是递归不够快速啊,所以快速幂自然还有非递归的啦:
ll ksm(ll b,ll p){ ll ans=1,base=b; while(p){ if(p&1){ ans*=base; ans%=k; } base*=base; base%=k; p/=2; } return ans; }
应该也很好理解吧(雾
时间复杂度$O(\log p)$
光速幂:
大概无前置知识?
光速幂适用于底数固定,模数固定的情况。
时间复杂度是$O(\sqrt{b})$($b$为指数)预处理,$O(1)$查询,适用范围并不广
其核心思想是设一个阈值$\omega$,预处理出$a^1,a^2,a^3...a^{\omega-1}$以及$a^{\omega},a^{2\times\omega},a^{3\times\omega}...a^{\lfloor\frac{b}{\omega}\rfloor\times\omega}$
那么$a^b$便可以转化为$a^{b\pmod\omega}\times a^{\lfloor\frac{b}{\omega}\rfloor\times\omega}$
根据均值不等式易证$\omega=\sqrt{b}$时时间复杂度最优
所以我们就得到了$O(\sqrt{b})$预处理,$O(1)$查询的光速幂/cy