快速幂,矩阵快速幂原理介绍

来源:互联网 发布:提花制版软件 编辑:程序博客网 时间:2024/05/17 04:20

快速幂:复杂度为logn,比普通的n快了很多了.

原理 :

以求a的b次方来介绍:首先把b转换成二进制数该二进制数第i位的权为  2^i - 1 .比如 : 11的二进制是101111 = 2³×1 + 2²×0 + 2¹×1 + 2º×1所以假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时           a^11=a^(2^0+2^1+2^3)

实现代码如下:(位运算,简单,简洁)

long long pow(int a,int b)  //位运算{    long long r=1,base=a;    while(b)    {        if(b&1)  r*=base;   //r才是最终我们要的结果.        base *= base ;     //一个中间转移量.b每右移一次,base就多一个平方.        b >>= 1 ;    }    return r;}

矩阵快速幂:

思想和快速幂差不多,只是这里是矩阵 , 而那个是数的差别.

所以原理和思想就不多说了 , 然后直接上代码

while(b){    if(b&1) res *= A;   //res是结果矩阵.    A *= A;           //和快速幂一样,每一次都是乘一个平方,因为最多也是差2的几次方的问题.    b >>= 1 ;}

难点在于如何构造A矩阵,只要构造出来了就简单了.
不知道怎么建矩阵的请看这里,这个讲的超级好[点这里, 点这里, 看见了吗, 点这里啊](http://www.cnblogs.com/frog112111/archive/2013/05/19/3087648.html
)
思路就是很简单:就是矩阵快速幂,主要是建好矩阵.

提供一个骚气的写法,就可以不用每一次写矩阵形式,就是重载 * 号运算符. 代码如下:

#define ll long long#define db double#define CLR(x) memset(x,0,sizeof(x))const int N=10;struct Ma{    db a[30][30];    void cc(){        CLR(a);    }    Ma operator * (const Ma &b) const {      //重载 * 号运算符.        Ma tmp;        tmp.cc();        for(int i=0;i<N;i++){            for(int j=0;j<N;j++){                for(int k=0;k<N;k++){                    if(b.a[k][j] == 0 || a[i][k] == 0)  continue;    //以后都把这个优化加//上, 在有些卡数的题中会遇到.(如某个校赛F题)因为一些稀疏矩阵就可以通过这样优化                    tmp.a[i][j] += (a[i][k] * b.a[k][j]);                    //tmp.a[i][j] %= mod;                }            }        }        return tmp;    }}res,x;     //有许多写法,这只是其中一种,我认为好理解点的!