[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); } }