• 斐波那契数列第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

  • 相关阅读:
    linux下18种监测网络带宽方式
    python常用正则表达式
    python获取当前路径
    python获取本机的IP
    Linux 误卸载自带python后的解决办法
    jmeter分布式运行
    jmeter非GUI的运行命令
    linux下安装jmeter
    java基础笔记(8)
    java基础笔记(7)
  • 原文地址:https://www.cnblogs.com/_inx/p/7631999.html
Copyright © 2020-2023  润新知