快速幂&矩阵快速幂算法小结

一、为什莫叫快速幂?矩阵快速幂又是什么?

快速幂,是根据幂的二进制最后一位0或1来加速进行乘法运算。
例如,在求5^19时,按照普通的求法就是要19个5相乘,这样虽然可以解出来,但当底数和指数都非常大时,这样计算的时间会很长,其时间复杂度为O(n)。但使用快速幂就要快速很多。其计算原理如下(下面底数用a表示,指数用n表示,下面的tmp初始为a,ans初始为1):
n=19的二进制是10011,
此时n为奇数,则ans=ans*tmp;tmp=tmp*tmp;n右移一位;(ans=1*5,tmp=5*5=25)
此时n为奇数,则ans=ans*tmp;tmp=tmp*tmp;n右移一位;(ans=5*25,tmp=25*25)
此时n为偶数,则直接tmp=tmp*tmp;n右移一位;(ans=125,tmp=625*625)
此时n为偶数,则直接tmp=tmp*tmp;n右移一位;(ans=125,tmp=390625*390625)
此时n为奇数,则ans=ans*tmp;tmp=tmp*tmp;n右移一位;(ans=125*390625*390625,tmp=(390625*390625)^2);
这样就已经求解成功,仅仅用了5次,大大节省了时间。其时间复杂度为O(logn)。

矩阵快速幂,顾名思义,就是矩阵做幂运算。其实际和快速幂差不多,只是需要对矩阵的乘法运算去做*运算符的重载。其中有一个重要的矩阵就是单位矩阵,他就相当于数字1一样,只是它是一个矩阵。例如2x2的单位矩阵为:
a【0】【0】=1;a【0】【1】=0;
a【1】【0】=0;a【1】【1】=1;

二、快速幂模板

#include<iostream>
using namespace std;

typedef long long ll;
const ll MOD=1000007;

ll quickPow(ll a,ll n){     //求a^n 
    ll tmp=a;
    ll ans=1;
    while(n){
        if(n&1){
            ans=ans*tmp;
        }
        tmp=tmp*tmp;
        n>>=1;
    }
    return ans;
}

int main(){

    //功能需求
    //............ 

    return 0;
}

三、矩阵快速幂模板

#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
const int Mod=100000007;

struct maxtri{
    ll v[2][2];
    maxtri (){
        memset(v,0,sizeof(v));      //初始化矩阵 
    }
    maxtri operator *(const maxtri &m){     //重载*运算符 
        maxtri tmp;
        for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
                for(int k=0;k<2;k++){
                    tmp.v[i][j]+=(v[i][k]*m.v[k][j])%Mod;
                }
            } 
        }
        return tmp;
    }
}; 
maxtri M,E,ans;     //M即为矩阵,E即为单位矩阵,ans为解 
void Init(){
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            if(i==j){
                E.v[i][j]=1;
            }
        }
    }
    M.v[0][0]=2;M.v[0][1]=1;        //具体情况具体值的初始化,这里是举例 
    M.v[1][0]=1;M.v[1][1]=0;
}   
maxtri quickPow(maxtri m,ll n){     //核心代码 
    maxtri tmp=E;
    while(n){
        if(n&1){
            tmp=tmp*m;
        }
        m=m*m;
        n>>=1;
    }
    return tmp;
}

int main(){

    //功能需求
    //............ 

    return 0;
}

四、快速幂及矩阵快速幂的应用

1、快速幂

主要是求指数幂

2、矩阵快速幂

    a.矩阵相乘;
    b.求菲波那切数列的第n项(就是可以从前两个状态推到当前状态,这个关系矩阵的系数还是比较好找的);

这里写图片描述

c.图论中求对应两个点长度为n的路径数,这是矩阵乘法在图论中的经典应用,其实就是用到了矩阵乘法的特殊性,因为矩阵乘法有三重循环,最里面的一层循环就是在枚举一个点k,i -> k -> j,那么从i -> j的路径数长度为m的条数就等于i-> k路径长度为n的路径数乘上k -> j路径长度为m - n的的路径条数,枚举的过程中全加起来,可以看到,这个过程和矩阵乘法的过程是一样的。矩阵An中的ai,j表示:图中点i到点j经过n条边的路径数。(只要能用矩阵乘法做的事情,一般都要用矩阵快速幂来假设)

猜你喜欢

转载自blog.csdn.net/wuyileiju__/article/details/81056150