warning:如果你还没有学过快速幂,请掉头先学快速幂因为快速幂的适用范围比这个东西更广
我们先回忆一下快速幂是怎么解决的
我们是利用二进制的性质将复杂度优化到单词询问O(logindex)O(\log index)O(logindex)
但是在有些题目中,可能复杂度不支持我们再在原有复杂度上增加一个log\loglog(比如询问变成10710^7107次)
那么这个时候就需要运用到光速幂的内容了
当我们计算ab mod pa^b \bmod pabmodp的时候,我们可以令b=ks+tb=ks+tb=ks+t,其中s,ts,ts,t是常数,t≤st\leq st≤s
那么我们只需要预处理出任意一个a0,a1,a2...asa^0,a^1,a^2...a^sa0,a1,a2...as,a0,as,a2s,a3s...a⌈ps⌉sa^0,a^s,a^{2s},a^{3s}...a^{\lceil\frac{p}{s}\rceil s}a0,as,a2s,a3s...a⌈sp⌉s,那么最后询问答案就是aks×bta^{ks}\times b^taks×bt就可以O(1)O(1)O(1)得到答案
那为什么我们的预处理的上界要取到ppp呢?其实应该上界是ϕ(p)\phi(p)ϕ(p),但是为了方便我们就算到ppp。
根据欧拉定理
aϕ(p)≡1 mod pab≡ab mod ϕ(p) mod p
\begin{aligned}
a^{\phi(p)}&\equiv 1\ &\bmod p \\
a^{b}&\equiv a^{b \bmod \phi(p)}\ &\bmod p
\end{aligned}
aϕ(p)ab≡1 ≡abmodϕ(p) modpmodp
也就是说,对于任意的aba^bab,一定有一个ac(c≤ϕ(p))a^c(c\leq\phi(p))ac(c≤ϕ(p))和他模ppp同余
那么显然当sss取⌈p⌉\lceil\sqrt p\rceil⌈p⌉时可以做到不漏的情况下复杂度最优
那么我们直接处理出这些幂就可以了
下面给出的是洛谷模板题代码,记得指数要 mod ϕ(p)\bmod\ \phi(p)mod ϕ(p)
#include <bits/stdc++.h>
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=1e5+5;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int a,b,p,bl;
int poww[N][2];
int phi(int x){
int res=x;
for(int i=2;i*i<=x;i++){
if(x%i==0)res=res/i*(i-1);
while(x%i==0)x/=i;
}
if(x>1)res=res/x*(x-1);
return res;
}
int Qpow(int ind){
ind%=phi(p);
return 1ll*poww[ind%bl][0]*poww[ind/bl][1]%p;
}
signed main()
{
read(a),read(b),read(p);
bl=sqrt(p)+1;
poww[0][0]=1;
Rep(i,1,bl)poww[i][0]=1ll*poww[i-1][0]*a%p;
poww[0][1]=1;
Rep(i,1,bl)poww[i][1]=1ll*poww[i-1][1]*poww[bl][0]%p;
printf("%d^%d mod %d=%d\n",a,b,p,Qpow(b));
return 0;
}
下面简单的分析一下光速幂和快速幂的优点缺点
| 性能 | 快速幂 | 光速幂 |
|---|---|---|
| 时间复杂度 | 单次询问O(logb)O(\log b)O(logb) | 预处理O(p)O(\sqrt p)O(p),询问O(1)O(1)O(1) |
| 空间复杂度 | $$ | |
| 应用范围 | 任何时候都可以使用 | 只有在底数相同,模数相同时可以使用 |
| 码量 | 短 | 比快速幂稍长(如果写ϕ\phiϕ的话) |
本文深入探讨了光速幂算法,一种在特定条件下优于快速幂的幂运算算法。通过预处理,光速幂能实现O(1)的时间复杂度进行模幂运算,尤其适用于大量询问的场景。文章详细解释了算法原理,包括欧拉定理的应用,以及如何通过优化预处理达到最佳性能。
1188

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



