快速幂和矩阵

快 速 幂 {\color{Red} 快速幂}

顾名思义:就是快速算某个数的多少次幂。
其时间复杂度为 O ( l g N ) O(lgN) O(lgN) 比朴素的 O ( N ) O(N) O(N)快了不知多少哈!

原理:

以下以求 a a a b b b 次方来介绍

b b b 转换成二进制数。该二进制数第 i i i 位的权为 2 i − 1 2^{i-1} 2i1;

例如:
11 11 11 的二进制是 1011 1011 1011,

11 = 2 3 ∗ 1 + 2 2 ∗ 0 + 2 1 ∗ 1 + 2 1 11=2^{3}*1+2^{2}*0+2^{1}*1+2^{1} 11=231+220+211+21;

因此,我们将 a 11 a^{11} a11 转化为算

a 2 0 ∗ a 2 1 ∗ a 2 3 a^{2^{0}}*a^{2^{1}}*a^{2^{3}} a20a21a23;

快 速 幂 {\color{Red} 快速幂} 可以用位运算来实现

b & 1//取b二进制的最低位,判断和1是否相同,相同返回1,否则返回0,可用于判断奇偶

b>>1//把b的二进制右移一位,即去掉其二进制位的最低位

下面是两种代码:

    int quickPow(int a,int b,int n)//递归形式
    {
      if(b==1)
        return a;
      if(b%2==0)//b是偶数;
        {
            int t=quickPow(a,b/2,n);
            return t*t%n;
        }
        else//b是奇数;
        {
            int t=quickPow(a,b/2,n);
            t=t*t%n;
            t=t*a%n;
            return t;
        }
    }


    int quickPow(int a,int b,int n)//非递归写法;
    {
        int ret=1;
        while(b)
        {
            if(b%2==1)
                ret=ret*a%n;
            a=a*a%n;
            b=b/2;
        }
        return ret;
    }

矩 阵 快 速 幂 {\color{Red} 矩阵快速幂}

既然说矩阵了那么就看看矩阵长成什么样吧!

[ a b c a 1 b 1 c 1 a 2 b 2 c 2 ] \begin{bmatrix} a& b &c \\ a1 & b1 &c1\\ a2&b2&c2 \end{bmatrix} aa1a2bb1b2cc1c2 ( a b c a 1 b 1 c 1 a 2 b 2 c 2 ) \begin{pmatrix} a& b &c \\ a1& b1 &c1 \\ a2& b2 &c2 \end{pmatrix} aa1a2bb1b2cc1c2

定 义 : {\color{Magenta} 定义:} :

m × n m × n m×n 个数 a i j aij aij排成的 m m m n n n列的数表称为 m m m n n n列的矩阵,简称 m ∗ n m * n mn矩阵。记作:

A= [ a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n a 31 a 32 . . . a 3 n . . . . . . . . . . . . a m 1 a m 2 . . . a m n ] \begin{bmatrix} a_{11}& a_{12} & ... & a_{1n} \\ a_{21} & a_{22} & ... & a_{2n}\\ a_{31}&a_{32}&...&a_{3n}\\ ... & ... & ... & ... \\ a_{m1} & a_{m2} & ... & a_{mn} \end{bmatrix} a11a21a31...am1a12a22a32...am2...............a1na2na3n...amn

m × n m×n m×n 个数称为矩阵 A A A的元素,简称为元,数 a i j a_{ij} aij位于矩阵 A A A的第 i i i行第 j j j列,称为矩阵 A A A ( i , j ) (i,j) (i,j)元,以数 a i j a_{ij} aij ( i , j ) (i,j) (i,j)元的矩阵可记为 ( a i j ) (a_{ij}) (aij) ( a i j ) (a_{ij}) (aij) m ∗ n m * n mn m ∗ n m*n mn矩阵 A A A也记作 A m n A_{mn} Amn

矩 阵 乘 法 {\color{Magenta}矩阵乘法} :

两个矩阵的乘法仅当第一个矩阵A的列数和另一个矩阵B的行数相等时才能定义。如A是m×n矩阵和B是n×p矩阵,它们的乘积C是一个m×p矩阵 ,它的一个元素:

c i , j = a i , 1 b 1 , j + a i , 2 b 2 , j + ⋅ ⋅ ⋅ + a i , n b n , j = ∑ r = 1 n a i , r b r , j c_{i,j}=a_{i,1}b_{1,j}+a_{i,2}b_{2,j}+\cdot \cdot \cdot +a_{i,n}b_{n,j}=\sum_{r=1}^{n}a_{i,r}b_{r,j} ci,j=ai,1b1,j+ai,2b2,j++ai,nbn,j=r=1nai,rbr,j;

并将此乘积记为: C = A B C=AB C=AB;

例如:

[ 1 0 2 − 1 3 1 ] ∗ [ 3 1 2 1 1 0 ] = [ ( 1 ∗ 3 + 0 ∗ 2 + 2 ∗ 1 ) ( 1 ∗ 1 + 0 ∗ 1 + 2 ∗ 0 ) ( − 1 ∗ 3 + 3 ∗ 2 + 1 ∗ 1 ) ( − 1 ∗ 1 + 3 ∗ 1 + 1 ∗ 0 ) ] = [ 5 1 4 2 ] \begin{bmatrix} 1 & 0 &2 \\ -1& 3 & 1 \end{bmatrix}*\begin{bmatrix} 3&1 \\ 2 & 1\\ 1 & 0 \end{bmatrix}=\begin{bmatrix} (1*3+0*2+2*1)&(1*1+0*1+2*0) \\ (-1*3+3*2+1*1)&(-1*1+3*1+1*0) \end{bmatrix}=\begin{bmatrix} 5 & 1 \\ 4 &2 \end{bmatrix} [110321]321110=[(13+02+21)(13+32+11)(11+01+20)(11+31+10)]=[5412];

矩阵的乘法满足以下运算律:

结合律: ( A B ) C = A ( B C ) (AB)C=A(BC) (AB)C=A(BC)
左分配律: ( A + B ) C = A C + B C (A+B)C=AC+BC (A+B)C=AC+BC
右分配律: C ( A + B ) = C A + C B C(A+B)=CA+CB C(A+B)=CA+CB

矩阵乘法一般不满足交换律。

代码如下:

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];
}

另一种写法:

int c[N][N];
void multi(int a[][N],int b[][N],int n)
{
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++)
        for(int k=1;k<=n;k++)
        for(int j=1;j<=n;j++)
        c[i][j]+=a[i][k]*b[k][j];
}

这种可以在第二重 f o r for for判断 i f ( a [ i ] [ k ] = = 0 ) c o n t i n u e ; if(a[i][k]==0)continue; if(a[i][k]==0)continue;对于矩阵有较多0的有一定效果。不过一般第一种写法就够了,这种知道就行。

显然矩阵乘法的复杂度是 O ( n 3 ) O(n^{3}) O(n3);( O ( n 2.7 ) O(n^{2.7}) O(n2.7)的方法不会写,无视这里)。

这里我直接写的是 n ∗ n n*n nn的矩阵(即方阵),显然两个相乘是要一行和一列对应乘,那么矩阵乘法是需要 A A A的行数与 B B B的列数相等的(这是 A ∗ B A*B AB的前提条件,可见矩阵的乘法是不满足交换律的)。然而这些一般都是没什么用的,矩阵快速幂只会用到方阵(除非题目是裸的矩阵乘法)。矩阵快速幂都是方阵也就避免的相乘的前提条件,可以放心用

矩 阵 快 速 幂 {\color{Magenta} 矩阵快速幂} :

就是算 A n A^n An;方法很简单,把快速幂算法中的乘法改成矩阵的乘法就可以了(网上搜的代码,????)

代码如下:

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是矩阵大小
    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=a*a
        n>>=1;
    }
}

不过上诉 r e s res res数组就等同于普通快速幂初始化的 1 1 1,原理想通的,这个矩阵叫单位矩阵E,性质就是 E ∗ A = A E*A=A EA=A,就是 1 ∗ a = a 1*a=a 1a=a,一样,单位矩阵就是对角线全是1其他全是 0 0 0,最终算出的结果是一个 r e s res res矩阵;

未 完 待 续 ⋅ ⋅ ⋅ ⋅ {\color{Red} 未完待续\cdot\cdot\cdot \cdot}

实践是检验真理的唯一标准

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值