P1939 模板矩阵加速(数列)

Posted buringstraw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1939 模板矩阵加速(数列)相关的知识,希望对你有一定的参考价值。

P1939 【模板】矩阵加速(数列)

同步更新于这里

题目描述

a[1]=a[2]=a[3]=1

a[x]=a[x-3]+a[x-1] (x>3)

求a数列的第n项对1000000007(10^9+7)取余的值。

输入输出格式

输入格式:

第一行一个整数T,表示询问个数。

以下T行,每行一个正整数n。

输出格式:

每行输出一个非负整数表示答案。

输入输出样例

输入样例#1:

3
6
8
10

输出样例#1:

4
9
19

说明

对于30%的数据 n<=100;

对于60%的数据 n<=2*10^7;

对于100%的数据 T<=100,n<=2*10^9;

解决

正如标题那样,模板题

A=[
1 1 0 0
0 0 1 0
1 0 0 1
0 0 0 0]
```

可能想不到的地方(我没想到的地方):

  • a[x]=a[x-3]+a[x-1] ,但x-2,x-4也可以放进矩阵里
  • n<=3时会死循环,要特判
#include<iostream>
#include<cstring>
#define min(a,b) ((a)>(b)?(b):(a))
#define max(a,b) ((a)<(b)?(b):(a))
using namespace std;
const long long MAXN=10,mo=1e9+7;

struct juzhen{
    public:
        juzhen(int han,int lin){
            h=han,l=lin;
            memset(v,0,sizeof(v));  
        }
        
        juzhen(){
            memset(v,0,sizeof(v));          
        }
        
        void cleanForPow(void){
            memset(v,0,sizeof(v));
            int p=min(h,l);
            for(int i=1;i<=p;++i){
                v[i][i]=1;
            }
        }
        
        friend juzhen operator *(juzhen a,juzhen b){
            juzhen c(a.h,b.l);
            if(a.l!=b.h)return c;
            
            for(int i=1;i<=a.h;++i){
                for(int j=1;j<=b.l;++j){
                    long long s=0;
                    for(int k=1;k<=a.l;++k){
                        s=s%mo+(a.v[i][k]*b.v[k][j]%mo);
                    }
                    c.v[i][j]=s;
                }
            }
            return c;
        }
        
        juzhen pow(int k){
            juzhen res=*this;
            juzhen ret(h,l);
            ret.cleanForPow();
            while(k){
                if(k&1){
                    ret=ret*res;
                }
                res=res*res;
                k>>=1;
            }
            return ret;
        }
        
        void setV(long long t[MAXN][MAXN]){
            for(int i=1;i<=h;++i){
                for(int j=1;j<=l;++j){
                    v[i][j]=t[i][j];
                }
            }
        }
        long long v[MAXN][MAXN];
        
    private:
        int h,l;
        
};

int main(void){
    int T;
    cin>>T;
    long long tmp[MAXN][MAXN]={{0},{0,2,1,1,1}};
    long long tmp2[MAXN][MAXN]={
        {0},
        {0,1,1,0,0},
        {0,0,0,1,0},
        {0,1,0,0,1},
        {0,0,0,0,0}
    };
    juzhen a(1,4);
    juzhen b(4,4);
    a.setV(tmp);
    b.setV(tmp2);
    while(T--){
        int n;
        cin>>n;
        if(n<=3)cout<<"1
",continue;
        juzhen ans=a*b.pow(n-4);
        cout<<ans.v[1][1]<<'
';
    }
    return 0;
}

以上是关于P1939 模板矩阵加速(数列)的主要内容,如果未能解决你的问题,请参考以下文章

P1939 模板矩阵加速(数列)

P1939 模板矩阵加速(数列)

[洛谷P1939]模板矩阵加速(数列)

P1939 模板矩阵加速(数列)

luogu P1939 模板矩阵加速(数列) 题解

[LGOJ]P1939模板矩阵加速(数列)[矩阵加速递推]