zoukankan      html  css  js  c++  java
  • 矩阵加速数列(学习笔记)

    当我们遇到这样一类问题:已知递推式,但数据范围太大,直接递推下去肯定会超时,例如求斐波拉契数列的第n项((n<=10^{18}))等等.这是我们就需要用到矩阵来加速递推,优化时间复杂度.

    步骤和思想都很简单.以求斐波拉契数列的第n项为例.我们已知递推式(f(n)=f(n-2)+f(n-1)),把等式两边各抽象为一个矩阵,即我们已知(S(n-1)=[f(n-1),f(n-2)]),要求出(S(n)=[f(n),f(n-1)]),那么(S(n-1))如何变换到(S(n))呢?可以乘上转移矩阵(T= [egin{matrix} 1 & 1 \1 & 0 end{matrix}]),这里可以自己根据矩阵乘法运算法则手玩出来.

    于是就可以设出初始矩阵(S(0)),然后(S(n)=S(0)*T^n),显然(T^n)可以通过矩阵快速幂来求得.my题解

    至于细节和实现直接结合模板题来看.我先说明一下,每个人的矩阵可能会有一些写法上的差别.

    洛咕

    题意:(a[1]=a[2]=a[3]=1);(a[x]=a[x-3]+a[x-1] (x>3)).求a数列的第n项对1e9+7取余的值.

    分析:模板题.已知矩阵为(S(n-1)=[f(n-1),f(n-2),f(n-3)]),目标矩阵为(S(n)=[f(n),f(n-1),f(n-2)]),通过手玩可得转移矩阵(T=[egin{matrix} 1 & 1 & 0\0 & 0 & 1\1 & 0 & 0end{matrix}]).

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    const int mod=1e9+7;
    struct matrix{//这是一个板子,重载了'*'
        int a[3][3];
        matrix operator *(matrix b){
    	matrix c;
    	for(int i=0;i<3;i++)
    	    for(int j=0;j<3;j++)
    			c.a[i][j]=0;
    //一定要记得初始化
    	for(int i=0;i<3;i++)
    	    for(int j=0;j<3;j++)
    			for(int k=0;k<3;k++)
    		    	c.a[i][j]=(c.a[i][j]+1LL*a[i][k]*b.a[k][j])%mod;
    		return c;
        }
    }S,T;
    int main(){
        int Q=read();
        while(Q--){
    		int n=read();
            if(n==1||n==2||n==3){
            	puts("1");
                continue;
            }
    		n-=3;
    //因为题目给了我们前三项,我们的初始矩阵就用前三项
    //所以我们需要特判前三项,特判通过之后n=n-3
    		S.a[0][0]=1;S.a[0][1]=1;S.a[0][2]=1;
    //构建出初始矩阵
    		T.a[0][0]=1;T.a[0][1]=1;T.a[0][2]=0;
    		T.a[1][0]=0;T.a[1][1]=0;T.a[1][2]=1;
    		T.a[2][0]=1;T.a[2][1]=0;T.a[2][2]=0;
    //构建出转移矩阵
    		while(n){if(n&1)S=S*T;T=T*T;n>>=1;}
    //快速幂
    		printf("%d
    ",S.a[0][0]);	
        }
        return 0;
    }
    
    

    洛咕

    题意:求斐波那契数列的第n项.

    分析:最开始那段文字已经写出来了.

    const LL mod=1e9+7;
    struct matrix{
        LL a[2][2];
        matrix operator *(matrix b){
    		matrix c;
    		for(int i=0;i<2;i++)
    	    	for(int j=0;j<2;j++)
    				c.a[i][j]=0;
    		for(int i=0;i<2;i++)
    	    	for(int j=0;j<2;j++)
    				for(int k=0;k<2;k++)
    		    		c.a[i][j]=(c.a[i][j]+1LL*a[i][k]*b.a[k][j])%mod;
    		return c;
        }
    }S,T;
    int main(){
        S.a[0][0]=1;S.a[0][1]=1;
        T.a[0][0]=1;T.a[0][1]=1;T.a[1][0]=1;T.a[1][1]=0;
        LL n=read();
        if(n==1||n==2){puts("1");return 0;}
        n-=2;
        while(n){if(n&1)S=S*T;T=T*T;n>>=1;}
        printf("%lld
    ",S.a[0][0]%mod);
        return 0;
    }
    
    

    洛咕

    题意:广义的斐波那契数列是指形如(a_n=p imes a_{n-1}+q imes a_{n-2})的数列.给定数列的两系数(p)(q),以及数列的最前两项(a_1)(a_2),另给出两个整数(n)(m),试求数列的第(n)(a_n)除以(m)的余数.

    分析:按照步骤列出已知矩阵(S(n-1)=[f(n-1),f(n-2)]),目标矩阵(S(n)=[f(n),f(n-1)]),手玩出转移矩阵(T=[egin{matrix} p & 1 \q & 0 end{matrix}]).(有一个要注意的地方:初始矩阵中(f(n-2)=a_1,f(n-1)=a_2)).

    LL p,q,a1,a2,n,m;
    struct matrix{
        LL a[2][2];
        matrix operator *(matrix b){
    		matrix c;
    		for(int i=0;i<2;i++)
    	    	for(int j=0;j<2;j++)
    				c.a[i][j]=0;
    		for(int i=0;i<2;i++)
    	    	for(int j=0;j<2;j++)
    				for(int k=0;k<2;k++)
    		    		c.a[i][j]=(c.a[i][j]+1LL*a[i][k]*b.a[k][j])%m;
    		return c;
        }
    }S,T;
    int main(){
        p=read();q=read();a1=read();a2=read();n=read();m=read();
        if(n==1){printf("%lld
    ",a1);return 0;}
        if(n==2){printf("%lld
    ",a2);return 0;}
    //本题貌似没有构造需要特判的数据
        n-=2;//n还是要-2
        S.a[0][0]=a2;S.a[0][1]=a1;
        T.a[0][0]=p;T.a[0][1]=1;
        T.a[1][0]=q;T.a[1][1]=0;
        while(n){if(n&1)S=S*T;T=T*T;n>>=1;}
        printf("%lld
    ",S.a[0][0]%m);	
        return 0;
    }
    
    
  • 相关阅读:
    Windows远程桌面跳板机无法复制粘贴
    无法打开“XXXX”,因为Apple无法检查其是否包含恶意软件。怎么解决?
    mac下的快捷键
    python:递归函数
    ps:新建Photoshop图像
    python-函数的参数
    python3-定义函数
    python3-调用函数
    python3-函数
    ps:界面概览
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10587909.html
Copyright © 2011-2022 走看看