快速幂的操作

快速幂

对大数时间复杂度的优化,具体操作是利用二进制操作

11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a(20)*a(21)*a(23) ,看出来快的多了吧原来算11次,现在算三次
& 运算还可以判断奇偶x&1== 0为偶,x&1== 1为奇

int powww ( int a, int b)
{
    int ans = 1;
    int ans = 1, base = a;
    while( b!= 0)
    {
        if(b &1 != 0)//&1 操作是取二进制的最末位
            ans *= base;
        base *= base;
        b >>= 1;// >>操作是二进制去掉最后一位
    }
    return ans;
}

以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a(20) * a(21) * a(23),是从左向右的。我们不断的让base*=base目的即是累乘,以便随时对ans做出贡献。

矩阵的快速幂

推荐 数组与矩阵的关系
矩阵的快速幂只需要将乘法换为矩阵的乘法就好了
写一个函数

//矩阵的乘法
const int N=100;
int c[N][N];
void multi(int a[][N],int b[][N],int n)//n是矩阵大小,n<N
{
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        c[i][j]+=a[i][k]*b[k][j];
}

完整代码

const int N=10;
int tmp[N][N];
void multi(int a[][N],int b[][N],int n)
{
memset(tmp,0,sizeof tmp);
 
for(int i=0;i<n;i++)
 
for(int j=0;j<n;j++)
 
for(int k=0;k<n;k++)
 
tmp[i][j]+=a[i][k]*b[k][j];
 
for(int i=0;i<n;i++)
 
for(int j=0;j<n;j++)
 
a[i][j]=tmp[i][j];
 
}
 
int res[N][N];
 
void Pow(int a[][N],int n)
 
{
 
memset(res,0,sizeof res);//n是幂,N是矩阵size
 
for(int i=0;i<N;i++) res[i][i]=1;
 
while(n)
{
if(n&1)
multi(res,a,N);//res=res*a;复制直接在multi里面实现了;
multi(a,a,N);//a的平方
n>>=1;
}
}

猜你喜欢

转载自blog.csdn.net/king9666/article/details/87628949