快速幂与矩阵快速幂

  快速幂,顾名思义要快速解决数幂问题 朴素算法中时间复杂度为O(n),在处理大数幂时显然会爆,这时要使用到快速幂的思想。

  对于一个数的6方A^6们通常使用A*A*A*A*A*A,此时计算机进行5乘法运算,但我们可以将其拆分为(A*A)*(A*A)*(A*A),这样做的优点在于当我们进行一次A*A运算后,只需将其乘3次即可得到结果,相比于原来的5次节约时间,在幂数更大一些时效果更佳明显。

  那么问题来了,对于一个简单的幂运算我们可以快速找出我们需要的那个基数幂,即上文的A*A,在幂更大时该如何找到我们需要的基数呢。这时在将大数离散化之后,会发生一些变化,例如

                                             A^156     将156呈2进制展开为 10011100  

                                         每一位1所代表的数位分别为 4  8  16  128   相加结果为156  那么我们可以得到

                                              A^4*A^8*A^16*A^128=A^156  这样我们就找到了需要的基数  A^4 

  于是可以从二进制右端计算到左端,

while(n)
{
    if(n&1)
        ans=ans*A;
    n>>=1;
    A=A*a;
}

将矩阵带入后便可以解决一些大面积递推问题。例如大位菲波那切数列问题。

现需要菲数列第1亿项模10^6,递推当然可以解决但是,电脑:我选择死亡∠( ᐛ 」∠)_。

f(1)=f(2)=1 f(n)=f(n-1)+f(n-2)  当我们用矩阵表示时 会得到

所以当我们需要更多位菲数列时,对中间的(1110)矩阵乘幂 便得到了


后在使用快速幂思想简化中间矩阵,便解决了矩阵快速幂问题,矩阵快速幂就是把快速幂中的运算方式换成矩阵运算,线性代数中有详细介绍,直接附上模板

#include<bits/stdc++.h>
using namespace std;
const int N=4;
int n;
struct xx
{
    int a[N][N];
    
};ori,res;
xx mul(xx x,xx y)
{
    xx temp;
    memset(temp.a,0,sizeof(temp,a));
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            for(int k=0;k<N;k++)
            {
                temo.a[i][j]+=x.a[i][k]*y.a[k][j];
            }
        }
    }
    return temp;
}
void init()
{
    int x;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            scanf("%d",&x);
            ori.a[i][j]=x;
        }
    }
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            res.a[i][j]=i==j?1:0;
        }
    }
}
xx calc(long long k)
{
    while(k)
    {
        if(k&2==1)
        {
            res=mul(ori,res);
            k-=1;
        }
        else
        {
            ori=mul(ori,ori);
            k/=2;
        }
    }
    return res.a[0][0];
}
int main()
{
    while(cin>>n)
    {
        init();
        calc(n);
    }
}








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值