码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-01-06 18:15:42      阅读:209      评论:0      收藏:0      [点我收藏+]

标签:struct   eof   memset   [1]   vat   friend   iostream   long   out   

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\n",continue;
        juzhen ans=a*b.pow(n-4);
        cout<<ans.v[1][1]<<'\n';
    }
    return 0;
}

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

标签:struct   eof   memset   [1]   vat   friend   iostream   long   out   

原文地址:https://www.cnblogs.com/buringstraw/p/10229190.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!