快速幂以及快速矩阵幂

来源:互联网 发布:赤月传说2麻痹升级数据 编辑:程序博客网 时间:2024/06/08 18:18
求幂是常见的运算,当然用朴素的循环做法很容易解决。但是在ACM中,当所要求的幂指数太大时,并且如果是在在循环当中,那么O(N)的时间复杂度往往不能达到ACM比赛要求的时间要求。因此快速幂是一种很好的求幂方法,简单易行,并且时间复杂度为O(logN),可以满足相当的时间要求。


PS:if(n&1)
     &符号表示取与运算,因为1的二进制表示最后一位为1,所以若是使n&1为真,那么n的二进制表示最后一位也是1,这样的话就证明了n也是奇数,因此,该取与运算是判断n是否为奇数的快速方法。
 
快速幂算法思路:
      因为   a^b mod c=(a^2)^(b/2) mod c  (b为偶数);
               a^b mod c=((a^2)^(b div 2)*a) mod c (b为奇数)
  所以可以在计算过程中不断地将底数平方、指数除以2,用另一个变量记录最终答案。

  得到快速幂算法:

int quickpow(int m,int n){    int ans=1;    while(n>0)    {        if(n&1)//n为奇数时,相乘一次;          ans=(ans*m)%mod;        n>>=1;        m=(m*m)%mod;//底数进行平方    }    return ans;}

对于矩阵相乘的运算,同样也有矩阵的快速幂运算,思路与上面相同,算法如下:

#include <stdio.h>#define MAXN 100const int mod=3001;  struct mat{    int n;    int date[MAXN][MAXN];      int *operator[](int i){//重载运算符       return date[i];    }      mat operator*(mat &b)//矩阵乘法    {        mat ans;ans.n=n;        int i,j,k;          for(i=1;i<=n;i++)           for(j=1;j<=n;j++)           {               ans[i][j]=0;               for(k=1;k<=n;k++)                  ans[i][j]+=(date[i][k]*b[k][j])%mod;                ans[i][j]%=mod;           }        return ans;    }};  mat matquickpow(mat &a,int b){    mat ans=a;b--;//由于此处ans=a,因此需要b-1;    while(b>0)    {        if(b&1)           ans=ans*a;        b>>=1;        a=a*a;    }    return ans;}  int main(){    int t,m,n,b;    scanf("%d",&t);      while(t--)    {        scanf("%d %d",&n,&b);        int i,j;          mat ans1;ans1.n=n;        for(i=1;i<=n;i++)           for(j=1;j<=n;j++)             scanf("%d",&ans1[i][j]);          mat a=matquickpow(ans1,b);          for(i=1;i<=n;i++)        {            for(j=1;j<=n;j++)              printf("%d ",a[i][j]);            printf("\n");        }    }}


原创粉丝点击