光速幂

warning:如果你还没有学过快速幂,请掉头先学快速幂因为快速幂的适用范围比这个东西更广

我们先回忆一下快速幂是怎么解决的
我们是利用二进制的性质将复杂度优化到单词询问 O ( log ⁡ i n d e x ) O(\log index) O(logindex)
但是在有些题目中,可能复杂度不支持我们再在原有复杂度上增加一个 log ⁡ \log log(比如询问变成 1 0 7 10^7 107次)
那么这个时候就需要运用到光速幂的内容了

当我们计算 a b   m o d   p a^b \bmod p abmodp的时候,我们可以令 b = k s + t b=ks+t b=ks+t,其中 s , t s,t s,t是常数, t ≤ s t\leq s ts
那么我们只需要预处理出任意一个 a 0 , a 1 , a 2 . . . a s a^0,a^1,a^2...a^s a0,a1,a2...as a 0 , a s , a 2 s , a 3 s . . . a ⌈ p s ⌉ s a^0,a^s,a^{2s},a^{3s}...a^{\lceil\frac{p}{s}\rceil s} a0,as,a2s,a3s...asps,那么最后询问答案就是 a k s × b t a^{ks}\times b^t aks×bt就可以 O ( 1 ) O(1) O(1)得到答案
那为什么我们的预处理的上界要取到 p p p呢?其实应该上界是 ϕ ( p ) \phi(p) ϕ(p),但是为了方便我们就算到 p p p
根据欧拉定理
a ϕ ( p ) ≡ 1     m o d   p a b ≡ a b   m o d   ϕ ( p )     m o d   p \begin{aligned} a^{\phi(p)}&\equiv 1\ &\bmod p \\ a^{b}&\equiv a^{b \bmod \phi(p)}\ &\bmod p \end{aligned} aϕ(p)ab1 abmodϕ(p) modpmodp
也就是说,对于任意的 a b a^b ab,一定有一个 a c ( c ≤ ϕ ( p ) ) a^c(c\leq\phi(p)) ac(cϕ(p))和他模 p p p同余

那么显然当 s s s ⌈ p ⌉ \lceil\sqrt p\rceil p 时可以做到不漏的情况下复杂度最优

那么我们直接处理出这些幂就可以了

下面给出的是洛谷模板题代码,记得指数要   m o d     ϕ ( 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 ( log ⁡ b ) O(\log b) O(logb)预处理 O ( p ) O(\sqrt p) O(p ),询问 O ( 1 ) O(1) O(1)
空间复杂度$$
应用范围任何时候都可以使用只有在底数相同,模数相同时可以使用
码量比快速幂稍长(如果写 ϕ \phi ϕ的话)
  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值