• 斐波那契数列第N项f(N)[矩阵快速幂]


    矩阵快速幂

    ---!x^n+y^n=z^n

      定义矩阵A(m*n),B(p*q),A*B有意义当且仅当n=p。即A的列数等于B的行数。

      且C=A*B,C(m*q)。

      例如:

      进入正题,由于现在全国卷高考不考矩阵,也没多大了解。因为遇到了斐波那契这题...

      注意到: Fn+1=Fn+Fn-1

      我们会有:

      则:

      所以我们只需要想办法求矩阵A的幂,这时候我们当然想要用快速幂。


    代码部分:

    定义矩阵:

    struct matrix{
        ll a[3][3];
    };

    (类比整数的快速幂)预处理:

    [我们需要一类似于1的矩阵:]

    『1 0 0

        0 1 0

        0 0 1』类似这种操作...

    void init(){
            int i,j;
            memset(res.a,0,sizeof res.a);
            for(i=1;i<=2;i++) res.a[i][i]=1;
            base.a[1][1]=1;
            base.a[1][2]=1;
            base.a[2][1]=1;
            base.a[2][2]=0;
    }

    矩阵乘法:[就该题而言]

    matrix mul(matrix p,matrix q){
            int i,j,k;
            matrix m;
            memset(m.a,0,sizeof m.a);
            for(i=1;i<=2;i++)
                for(j=1;j<=2;j++)
                    for(k=1;k<=2;k++)
                        m.a[i][j]=(m.a[i][j]+p.a[i][k]*q.a[k][j])%Mod;
            return m;
    }

    快速幂:

    void mfpow(ll p){
            init();
            while(p){
                if(p&1) res=mul(base,res);
                base=mul(base,base);
                p>>=1;
            } 
     }

    全部的代码:(lowbee的难免会差一些,请大佬们见谅...)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll ;
     6 inline ll read();
     7 const ll Mod = 1e9 + 7 ;
     8 struct matrix{
     9     ll a[3][3];
    10 };
    11 matrix res,base;
    12 ll ans;
    13 ll c[3];
    14 ll n;
    15 namespace lys{
    16     void init(){
    17         int i,j;
    18         memset(res.a,0,sizeof res.a);
    19         for(i=1;i<=2;i++) res.a[i][i]=1;
    20         base.a[1][1]=1;
    21         base.a[1][2]=1;
    22         base.a[2][1]=1;
    23         base.a[2][2]=0;
    24     }
    25     matrix mul(matrix p,matrix q){
    26         int i,j,k;
    27         matrix m;
    28         memset(m.a,0,sizeof m.a);
    29         for(i=1;i<=2;i++)
    30             for(j=1;j<=2;j++)
    31                 for(k=1;k<=2;k++)
    32                     m.a[i][j]=(m.a[i][j]+p.a[i][k]*q.a[k][j])%Mod;
    33         return m;
    34     }
    35     void mfpow(ll p){
    36         init();
    37         while(p){
    38             if(p&1) res=mul(base,res);
    39             base=mul(base,base);
    40             p>>=1;
    41         } 
    42     }
    43     int main(){
    44         int k;
    45         n=read();
    46         mfpow(n-1);
    47         c[1]=1;
    48         c[2]=0;
    49         for(k=1;k<=2;k++)
    50             ans=(ans+res.a[1][k]*c[k])%Mod;    
    51         cout<<ans<<endl;    
    52         return 0;    
    53     }
    54 }
    55 int main(){
    56     lys::main();
    57     return 0;
    58 }
    59 inline ll read(){
    60     ll k=0,f=1;
    61     char c=getchar();
    62     while(c<'0'||c>'9'){
    63         if(c=='-')
    64             f=-1;
    65         c=getchar();
    66     }
    67     while(c>='0'&&c<='9'){
    68         k=k*10+c-'0';
    69         c=getchar();
    70     }
    71     return k*f;
    72 }

    题目链接[luogu]:

    https://www.luogu.org/problem/show?pid=1962

  • 相关阅读:
    求正整数N(N>1)的质因数的个数。
    手机键盘输入字母
    第二部分进度
    第一部分:地域维度标准化
    利用python解析地址经纬度
    输入任意4个字符(如:abcd), 并按反序输出(如:dcba)
    python-->微信支付
    python-图片流传输(url转换二维码)
    python-qrcode-二维码
    ajax和axios、fetch的区别
  • 原文地址:https://www.cnblogs.com/_inx/p/7631999.html
Copyright © 2020-2023  润新知