【矩阵快速幂】数列

[NOIP模拟赛]数列

【题目描述】
  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。


【输出格式】
  每行输出一个非负整数表示答案。


【样例输入】
3
6
8
10


【样例输出】
4
9
19


【数据范围】
  对于30%的数据 n<=100;
  对于60%的数据 n<=2*10^7;
  对于100%的数据 T<=100,n<=2*10^9;

试题分析:60%直接递推就好

     至于100%的就用矩阵快速幂。

     0 1 0              1

     0 0 1 ^ (k-2) * 1

     1 0 1              1

 

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
#define LL long long
LL m1[7][7];
LL m2[7][7];
LL m3[7][7];
int N;
const int mod=1000000007;

void cheng(){
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++)
		    m2[i][j]=m3[i][j];
	}
	memset(m3,0,sizeof(m3));
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++){
			for(int k=1;k<=N;k++)
			    m3[i][j]+=m2[i][k]*m1[k][j]%mod,m3[i][j]%=mod;
		} 
	}
}
void cheng2(){
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++)
		    m2[i][j]=m1[i][j];
	}
	memset(m1,0,sizeof(m1));
	for(int i=1;i<=N;i++){
		for(int j=1;j<=N;j++){
			for(int k=1;k<=N;k++)
			    m1[i][j]+=m2[i][k]*m2[k][j]%mod,m1[i][j]%=mod;
		}
	}
}
void Pow(int b){
	while(b){
		if(b&1) cheng();
		b>>=1;
		cheng2();
	}
	return ; 
}
void chengk(){
	for(int a=1;a<=3;a++)
	    for(int b=1;b<=1;b++)
	        for(int c=1;c<=3;c++)
	            m1[a][b]+=m3[a][c]*m2[c][b]%mod,m1[a][b]%=mod;
	return; 
}
int main(){
	int T=read();
	while(T--){
		int k=read(); N=3;
		memset(m1,0,sizeof(m1));
		memset(m3,0,sizeof(m3));
		m1[1][2]=m3[1][2]=1;
		m1[2][3]=m3[2][3]=1;
		m1[3][1]=m3[3][1]=1;
		m1[3][3]=m3[3][3]=1;
		Pow(max(k-2,0));
		memset(m1,0,sizeof(m1));
		m2[1][1]=1,m2[2][1]=1,m2[3][1]=1;
		chengk();
		printf("%lld
",m1[1][1]%mod); 
	}
}
原文地址:https://www.cnblogs.com/wxjor/p/7357174.html