zoukankan      html  css  js  c++  java
  • 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;

    解决

    正如标题那样,模板题

    [f[x],f[x-1],f[x-2],f[x-3]]=[f[x-1],f[x-2],f[x-3],f[x-4]]*A

    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;
    }
    
  • 相关阅读:
    AQS共享锁应用之Semaphore原理
    AQS与重入锁ReetrantLock原理
    2018第23周总结
    阅读思考——被误用的敏捷和阻碍程序员成长的坏习惯
    百度云盘下载工具
    线程中断总结
    JUC包中的锁框架
    Java并发实现线程阻塞原语LockSupport
    react的类型检查PropTypes自React v15.5起已弃用,请使用prop-types
    python性能优化、内存优化、内存泄露;与其他语音比较效率如何?
  • 原文地址:https://www.cnblogs.com/buringstraw/p/10229190.html
Copyright © 2011-2022 走看看