快速幂(详解位运算法)和矩阵快速幂

18 篇文章 0 订阅
1 篇文章 0 订阅

1.基本快速幂

幂运算an即n个a相乘。快速幂就是高效的算出an,当n很大的时候,写题的话基本就超时了。当然基本的快速幂也不只一种方法,下面介绍一种用位运算实现的方法:

首先,就是要把n看成二进制,例如计算a11,实则就是计算a(1101)B,也就是最终可以转化为a(8+2+1)即是a8×a2×a1。如下图
在这里插入图片描述
那么显然,用位运算去遍历n的每一位(遍历n的每一位只要用n和1 做与运算,再每一将n右移一次即可),只要是该位为1,那么我们就要乘上一个ak,k肯定就是对应位的权值,例如已经遍历到(1101)B的最高位,发现是1,那么此时这个位置对应的权值是8,所以我们应该再乘上a8。因为是二进制,所以相对高一位的k肯定是低一位的k的两倍,对应的ak肯定就成平方关系,如下图。
在这里插入图片描述
而且我们还能知道第一个要乘的肯定就是a,也就是a的20次方,所以最低位要乘的数我们永远都知道,而且又知道高一位又是低一位的平方,所以我们只要定义一个变量,假如变量名为base,初始值为a,只要往高位走了一位就执行base*=base。这样下次可能要乘的值就很容易的求出来了,那么用于保存答案的变量ans是否要乘以base就靠位运算判断了,n对应位置的对应数值为1就乘,反之不乘。最终结束的条件自然是n对应二进制的最高位也已经遍历完。
代码

int fastpow(int a,int n)
{
    int base = a;
    int ans = 1;
    while(n)
    {
        if(n & 1)
            ans*=base;
        base*=base;
        n>>=1;
    }
    return ans;
}

快速幂一般值会很大,一般需要取模

int fastpow(int a,int n)
{
    int base = a;
    int ans = 1;
    while(n)
    {
        if(n & 1)
            ans = (ans*base)%mod;
        base = (base*base)%mod;
        n>>=1;
    }
    return ans;
}

2.矩阵快速幂

前提学习:线性代数矩阵乘法。
给定一个m×m的矩阵A,求它的n次幂,An。矩阵乘法关键是要用定义好矩阵相乘的操作,无论是重载还是写函数,都要有明确的定义。中心思想还是与基本的快速幂是相同的,所以理解基本的快速幂也是十分必要的。有区别的还是一些定义操作:

const int MAXN=2;  //阶数
const int mod=1e4;//模
struct matrix//定义矩阵
{
    int m[MAXN][MAXN];
    matrix(){
    memset(m,0,sizeof(m));}
};
matrix multi(matrix a,matrix b)//定义矩阵乘法
{
    matrix ans;
    for(int i=0;i<MAXN;+i++)
        for(int j=0;j<MAXN;++j)
            for(int k=0;k<MAXN;++k)
               ans.m[i][j]=(ans.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
    return ans;
}

定义好一系列的操作以后,就可以写快速幂函数了,这和基本的快速幂是很相似的:

matrix fastm(matrix a,int n)
{
    matrix ans;
    for(int i=0;i<MAXN;++i)//初始化单位矩阵
        ans.m[i][i]=1;
    while(n)
    {
        if(n & 1)
            ans=multi(ans,a);
        a=multi(a,a);
        n>>=1;
    }
    return ans;
}

2.1递推转矩阵

应用矩阵快速幂的难点并不是把这个代码理解(当然理解是必要的),而是如何把一段递推关系转化为矩阵。经典的例子就是斐波那契数列,f(n)=f(n-1)+f(n-2),很显然,用基本的快速幂是无法应用的,此时就可以用矩阵快速幂。如下图:
在这里插入图片描述
所以只要构造好转移矩阵,只要用矩阵快速幂算出Tn-1,再用矩阵乘法得出矩阵A(n),答案就是A(n)左上角的元素(一般而言,具体情况视矩阵设计而定)。所以说,这种题目的关键是通过递推关系找出转移的矩阵递推式,然后结合快速幂进行运算。

相应题目
HDU 3117

HDU 6030

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值