快速幂

普通快速幂

       快速幂就是快速求an直接for循环的时间复杂度是o(n),比较low。那么如何提高时间复杂度呢,幂的本质是连乘,其中b可以写成二进制,拆成2的幂。拿a的11次方为例,11的二进制是1011,所以可以得到11=20+21+23,于是,a的11次方可以写成a^20 * a^21 * a^23,这样就变成三个数的乘积了,快了很多,那么怎么求这三个数呢,看看我们怎么写出这三个数的,没错,就是二进制,位数就是2的幂,整个流程就是从右往左搞,0就不管他,1就将a^2n乘进ans。注意下方代码的ll代表long long 数据类型,使用本文代码请加上 typedef long long ll;

迭代

ll mypow(ll x,ll n){
    ll res=1;
    while(n){
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}

递归

思想是把a的n次方变成两个a的n/2次方相乘,就像2的100次方等于4的五十次方=8的25次方……

ll pow_mod(ll x,ll n,ll mod){
  if(n==0) return 1;
  ll res=pow_mod(x*x%mod,n/2,mod);
  if(n&1) res=res*x%mod;//在本层,如果b是奇数,意味着上一步会少乘了一个a,所以补上
  return res;
}

矩阵快速幂

原理是一样的,用单位矩阵作为初始矩阵进行迭代:

struct node{
    ll m[maxn][maxn];
};
node mul(node x,node y,int len){
    node res;
    for(int i=1;i<=len;i++)
        for(int j=1;j<=len;j++){
            res.m[i][j]=0;
            for(int k=1;k<=len;k++)
                res.m[i][j]=(res.m[i][j] + x.m[i][k]*y.m[k][j]%mod)%mod;
        }
            
    return res;
}

node mapow(node A,int len,ll n){
    node res;memset(res.m,0,sizeof(res.m));
    for(int i=1;i<=len;i++) res.m[i][i]=1;
    while(n){
        if(n&1) res=mul(res,A,len);
        A=mul(A,A,len);
        n>>=1;
    }
    return res;
}

 

 

 

 

 

 

 

posted @ 2019-03-29 17:34  艾尔夏尔-Layton  阅读(194)  评论(0编辑  收藏  举报